前端拖拽排序实现详解:从原理到实践 - 附完整代码

前端拖拽排序实现详解:从原理到实践 - 附完整代码
在这里插入图片描述
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》专栏19年编写主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
🌛《开源项目》本专栏主要介绍目前热门的开源项目,带大家快速了解并轻松上手使用
🍎 《前端技术》专栏以实战为主介绍日常开发中前端应用的一些功能以及技巧,均附有完整的代码示例
✨《开发技巧》本专栏包含了各种系统的设计原理以及注意事项,并分享一些日常开发的功能小技巧
💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整
👍《Spring Security》专栏中我们将逐步深入Spring Security的各个技术细节,带你从入门到精通,全面掌握这一安全技术
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

前端拖拽排序实现详解:从原理到实践 - 附完整代码

1. 前言

在我们前端开发过程中经常会用到排序的功能,其中列表项的拖拽排序(Drag-and-Drop Sortable)不仅能让用户直观、高效地调整顺序,还能大幅提升交互体验。无论是管理后台的菜单排序、看板(Kanban)中任务卡片的调整,还是移动端的图片/视频重排,拖拽排序都是不可或缺的交互模式。

在这里插入图片描述


本文博主将带着小伙伴从零开始,用原生 HTML5 Drag & Drop API 实现一个简洁的可拖拽排序列表,并模拟向后端提交新顺序的完整流程。


2. 拖拽排序的应用

任务管理工具
用户可以拖拽卡片改变优先级或在不同分组间移动(如Trello

内容管理系统
页面元素排序(如WordPress

图片/视频排序
相册管理、商品轮播图顺序调整

问卷表单选项
管理问答列表时,调整题目或选项顺序更直观

自定义导航菜单
后台可视化拖拽菜单层级与顺序

这些场景下,通过拖拽排序,用户无需点上下箭头、输入序号,就能快速完成调整,显著提升效率与体验。


3. 核心实现原理

3.1 HTML5拖放API基础

在这里插入图片描述


HTML5 Drag & Drop 原生 API 核心流程如下:

  • 设定可拖拽元素:draggable="true"
  • 监听拖拽开始:dragstart 事件,记录当前拖拽项索引或标识
  • 允许拖拽进入目标:在目标元素或容器上 dragover 事件中调用 event.preventDefault()
  • 处理放置:drop 事件中获取拖拽项和目标项索引,完成 DOM 位置交换。
  • 结束拖拽:可选的 dragend 事件,用于清理样式或状态。

3.2 关键事件解析

默认拖放API具备以下几个事件类型:

事件类型触发时机常用操作
dragstart开始拖拽元素时设置被拖拽元素的ID
dragenter进入目标元素时添加视觉反馈
dragover在目标元素上悬停时阻止默认行为(允许放置)
dragleave离开目标元素时移除视觉反馈
drop在目标元素上释放时处理元素位置交换
dragend拖拽操作结束时清理状态

4. 完整示例代码

下面是一个最小可运行的示例,小伙伴们可以复制至本地测试运行,注意后端排序保存已经将当前顺序的 ID 数组传递,后端接口小伙伴们自行实现即可

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>拖拽排序示例</title><style>body{font-family: sans-serif;padding: 20px;}#sortable-list{list-style: none;padding: 0;width: 300px;margin: 0 auto;}#sortable-list li{padding: 10px 15px;margin-bottom: 8px;background: #f0f0f0;border: 1px solid #ddd;cursor: move;user-select: none;}/* 拖拽时样式 */.dragging{opacity: 0.5;}.over{border-top: 2px solid #007bff;}</style></head><body><h2>拖拽排序示例</h2><ulid="sortable-list"><lidata-id="1"draggable="true">项目 1</li><lidata-id="2"draggable="true">项目 2</li><lidata-id="3"draggable="true">项目 3</li><lidata-id="4"draggable="true">项目 4</li><lidata-id="5"draggable="true">项目 5</li></ul><buttonid="saveOrderBtn">保存顺序</button><script>const list = document.getElementById('sortable-list');let dragSrcEl =null;functionhandleDragStart(e){ dragSrcEl =this;this.classList.add('dragging'); e.dataTransfer.effectAllowed ='move'; e.dataTransfer.setData('text/plain',this.dataset.id);}functionhandleDragOver(e){ e.preventDefault();// 必须阻止默认,才有 drop 事件 e.dataTransfer.dropEffect ='move';returnfalse;}functionhandleDragEnter(e){if(this!== dragSrcEl){this.classList.add('over');}}functionhandleDragLeave(e){this.classList.remove('over');}functionhandleDrop(e){ e.stopPropagation();// 阻止事件冒泡if(dragSrcEl !==this){// 在 DOM 中交换位置const nodes = Array.from(list.children);const srcIndex = nodes.indexOf(dragSrcEl);const targetIndex = nodes.indexOf(this);if(srcIndex < targetIndex){ list.insertBefore(dragSrcEl,this.nextSibling);}else{ list.insertBefore(dragSrcEl,this);}}returnfalse;}functionhandleDragEnd(e){// 清理样式this.classList.remove('dragging'); Array.from(list.children).forEach(item=>{ item.classList.remove('over');});}// 绑定事件 Array.from(list.children).forEach(item=>{ item.addEventListener('dragstart', handleDragStart); item.addEventListener('dragenter', handleDragEnter); item.addEventListener('dragover', handleDragOver); item.addEventListener('dragleave', handleDragLeave); item.addEventListener('drop', handleDrop); item.addEventListener('dragend', handleDragEnd);});// 模拟后端提交新顺序 document.getElementById('saveOrderBtn').addEventListener('click',()=>{const order = Array.from(list.children).map(li=> li.dataset.id); console.log('新的顺序:', order);// 示例:POST 到 /api/update-orderfetch('/api/update-order',{ method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ order })}).then(res=>{if(!res.ok)thrownewError('保存失败');return res.json();}).then(data=>{alert('顺序保存成功!');}).catch(err=>{ console.error(err);alert('保存失败,请重试');});});</script></body></html>

要点说明:

1、每个 <li> 元素设置了 draggable="true"data-id 作为唯一标识;
2、dragstart 时记录源元素并设置拖拽数据;
3、dragover 必须 preventDefault(),否则无法触发 drop
4、drop 事件中根据源元素和目标元素在父容器中的索引,动态交换位置;
5、点击“保存顺序”按钮后,将当前顺序的 ID 数组发送给后端接口 /api/update-order,完成持久化。

5. 结语

通过上述示例,相信小伙伴们已经掌握了使用原生 HTML5 Drag & Drop API 实现前端拖拽排序的全流程:从可拖拽元素配置、事件监听,到 DOM 顺序交换,再到模拟后端提交。

该方案无需引入第三方库,也足够轻量易懂。可以根据项目需求进一步优化:

  • 性能优化:对大型列表使用虚拟化或节流拖拽事件。
  • 视觉增强:使用动画(CSS transition)平滑排序过程。
  • 多容器拖拽:扩展至跨列表、跨分组的拖拽。
  • 第三方库:在复杂场景下可结合 SortableJSDragula 等成熟库。

希望本文能帮助小伙伴们快速在项目中落地拖拽排序功能,如果你在实践过程中有任何疑问或更好的扩展思路,欢迎在评论区留言,最后希望大家一键三连给博主一点点鼓励!


Read more

本地服务器部署Text generation并添加code llama实现远程多人协作

本地服务器部署Text generation并添加code llama实现远程多人协作

文章目录 * 前言 * 1. 本地部署Text generation Web UI * 2. 安装CodeLlama大模型 * 3. 实现公网远程使用Code Llama * 4. 固定Text generation Web UI公网地址 前言 本篇文章介绍如何在本地部署Text generation Web UI并搭建Code Llama大模型运行,并且搭建Code Llama大语言模型,结合Cpolar内网穿透实现公网可远程使用Code Llama。 Code Llama是一个可以使用文本提示生成代码的大型语言模型 (LLM)。可以使当前开发人员的工作流程更快、更高效,并降低学习编码人员的进入门槛。 Code Llama 有潜力用作生产力和教育工具,帮助程序员编写更强大、文档更齐全。 Text generation Web UI部署非常简便,不仅在github主页上直接提供了一键部署安装包,同时由于是web UI形式,直接通过浏览器即可操作,不过本地化部署,无法远程访问,这里我们结合cpolar工具实现从安装到最后实现远程访问。 那么接下来先在本地部署一

Qwen-Image-Edit-2511让AI绘画更有逻辑,空间关系更准

Qwen-Image-Edit-2511让AI绘画更有逻辑,空间关系更准 你有没有试过这样编辑一张图:想把照片里沙发左边的绿植换成一盏落地灯,结果AI不仅把灯放歪了,还让灯罩朝向窗外、影子却打在天花板上?或者给产品图换背景时,明明提示“纯白无影”,生成的阴影却像被风吹斜了三十度? 更让人挠头的是——你反复强调“人物站在门框正中央”,可AI总把人往右偏两厘米;你说“茶几在沙发前方一米处”,它却生成出茶几腿悬空半截的诡异构图。 这不是你提示词写得不够细,而是大多数图像编辑模型根本没真正理解‘左/右/前/后/上/下’这些空间关系。它们靠统计关联猜位置,而不是用几何逻辑推理布局。 直到我试了 Qwen-Image-Edit-2511 ——这个刚发布的增强版图像编辑镜像,第一次让我觉得:AI开始“看懂”画面里的三维世界了。 它不是又一个参数堆出来的“更大更快”,而是一次对空间语义的重新校准。下面这趟实测,我会带你亲眼看看:什么叫“让AI绘画真正讲逻辑”。 1. 它到底强在哪?不是修图,是重建空间认知 Qwen-Image-Edit-2511 是 Qwen-Image-Edit-2

Stable Diffusion XL 1.0镜像免配置方案:灵感画廊开箱即用部署指南

Stable Diffusion XL 1.0镜像免配置方案:灵感画廊开箱即用部署指南 1. 什么是灵感画廊:艺术创作的静谧空间 灵感画廊(Atelier of Light and Shadow)是一款基于Stable Diffusion XL 1.0打造的沉浸式艺术创作工具。它彻底摒弃了传统AI绘画工具的复杂界面和技术门槛,为你提供了一个纯粹、静谧的创作环境。 想象一下:不需要学习复杂的参数调节,不需要理解晦涩的技术术语,只需要打开浏览器,输入你的创意想法,就能生成高质量的艺术作品。这就是灵感画廊的核心价值——让艺术创作回归本质,让技术成为隐形的助手。 这个镜像已经预先配置好了所有必要的环境依赖和模型文件,你只需要简单的几步操作,就能拥有一个专业级的AI艺术创作工作室。 2. 快速部署:10分钟搭建你的私人画廊 2.1 环境准备与一键启动 首先确保你的系统满足以下基本要求: * NVIDIA显卡(建议8GB以上显存) * 已安装Docker环境 * 稳定的网络连接 部署过程非常简单,只需要执行以下命令: # 拉取灵感画廊镜像 docker

3步搞定Whisper-WebUI在Mac上的安装难题

3步搞定Whisper-WebUI在Mac上的安装难题 【免费下载链接】Whisper-WebUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisper-WebUI 还在为Whisper-WebUI在MacOS上的安装头疼吗?🤔 别担心,这篇文章将带你轻松解决这个困扰无数Mac用户的常见问题。作为一款优秀的语音转文字工具,Whisper-WebUI在Mac上的安装其实比你想象的简单得多! 🎯 实战场景:当语音识别遇上MacOS 想象一下这样的场景:你刚拿到全新的MacBook,想要体验Whisper-WebUI的强大语音识别功能,却在安装过程中遭遇各种"拦路虎"。这就像买到了心仪的新车,却发现没有合适的驾照一样令人沮丧。 很多Mac用户第一次接触Whisper-WebUI时都会遇到类似的困境:系统明明检测到了硬件,却总是提示使用CPU而非GPU;好不容易开始下载模型,Python进程却突然崩溃;终端里还不断跳出各种资源泄漏警告。这些问题看似复杂,其实都有简单的解决方案。 🚧 核心挑战:为什么MacOS如此"挑剔"? 硬件