Vue.Draggable 完整使用指南:基于 Sortable.js 的 Vue 2 拖拽组件从入门到进阶
Vue.Draggable 完整使用指南基于 Sortable.js 的 Vue 2 拖拽组件从入门到进阶【免费下载链接】Vue.DraggableVue drag-and-drop component based on Sortable.js项目地址: https://gitcode.com/gh_mirrors/vu/Vue.DraggableVue.Draggable 是运行在 Vue.js 2.0 上的拖拽组件底层基于 Sortable.js让任何列表、表格、手风琴甚至嵌套结构都能获得拖拽排序能力并自动把 DOM 变化同步回 view model 数组。本文以仓库 README.md 为主线结合 核心源码 与 示例目录完整讲解安装、典型用法、全部 Props、事件系统、插槽与常见陷阱帮助你在一篇文章内掌握可复制的实战方案。项目定位与核心特性Vue.Draggable 是一个 Vue 组件Vue 2.0或指令Vue 1.0用于实现拖拽并与 view model 数组保持同步。它基于并完整继承 Sortable.js 的能力包括完整支持 Sortable.js 的功能支持触摸设备支持拖拽手柄drag handles与可选文本智能自动滚动smart auto-scrolling支持在不同列表之间拖拽跨列表拖放无 jQuery 依赖。保持 HTML 与 view model 列表同步兼容 Vue.js 2.0 的transition-group支持取消拖拽操作cancellation事件系统可在需要完全控制时报告任何变更可复用现有 UI 库组件如 vuetify、element、vue material 等通过tag与componentDataProps 让它们变得可拖拽。从源码看组件在mounted钩子中创建 Sortable 实例// src/vuedraggable.js this._sortable new Sortable(this.rootContainer, options); this.computeIndexes();在beforeDestroy钩子中销毁实例src/vuedraggable.js确保组件卸载时不残留事件监听。组件的name为draggable若在浏览器环境检测到全局Vue还会自动注册为全局组件src/vuedraggable.js。注意本仓库对应 Vue 2.0 版本npm 包名为vuedraggable。Vue 3 用户请使用 SortableJS 官方提供的vue.draggable.next项目而vue-draggable带连字符是 Vue 1.0 的包安装时务必区分。安装方式使用 npm 或 yarnyarn add vuedraggablenpm i -S vuedraggable本仓库的 package.json 中依赖为sortablejs: 1.10.2当前版本号为2.24.3package.json。使用 CDN 直接引入script src//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js/script !-- CDNJS :: Sortable (https://cdnjs.com/) -- script src//cdn.jsdelivr.net/npm/sortablejs1.8.4/Sortable.min.js/script !-- CDNJS :: Vue.Draggable (https://cdnjs.com/) -- script src//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js/script完整可运行的示例可以查看仓库的 example 目录其中包含多个独立场景。基本用法Vue 2.0典型用法在模板中直接使用draggable组件通过v-model绑定数组并给每个子元素提供唯一的keydraggable v-modelmyArray grouppeople startdragtrue enddragfalse div v-forelement in myArray :keyelement.id{{element.name}}/div /draggable在.vue文件中注册组件import draggable from vuedraggable // ... export default { components: { draggable, }, // ... }在 example/components/simple.vue 中可以看到完整可运行示例它使用:list绑定数组通过:move校验拖放、用start/end切换拖拽中的状态文案并监听ghost-class等属性。配合 transition-group 使用draggable v-modelmyArray transition-group div v-forelement in myArray :keyelement.id {{element.name}} /div /transition-group /draggable关键约束draggable 组件应当直接包裹可拖拽元素或者包裹一个transition-component即transition-group再由它包裹可拖拽元素。源码中的isTransition函数会检测默认插槽是否恰好只有一个transition-group/TransitionGroup子节点src/vuedraggable.js检测通过后进入transitionMode此时 Sortable 作用于this.$el.children[0]即 transition-group 的实际根节点见rootContainer计算属性 src/vuedraggable.js。使用 footer / header 插槽在draggable元素前后追加“不可拖拽”的内容如添加按钮draggable v-modelmyArray draggable.item div v-forelement in myArray :keyelement.id classitem {{element.name}} /div button slotfooter clickaddPeopleAdd/button /draggabledraggable v-modelmyArray draggable.item div v-forelement in myArray :keyelement.id classitem {{element.name}} /div button slotheader clickaddPeopleAdd/button /draggable注意使用插槽时必须配合draggable.item之类的选择器来标记可拖拽元素。实现上源码在computeChildrenAndOffsets中会把 header 插槽内容拼接到默认插槽之前、footer 插槽内容拼接到默认插槽之后并记录headerOffset/footerOffset拖拽结束时这些偏移量会被加入索引计算src/vuedraggable.js。与 Vuex 集成valueprop 只读因此与 Vuex 天然兼容在 computed 中提供 get/set把 set 转发给 mutationcomputed: { myList: { get() { return this.$store.state.myList }, set(value) { this.$store.commit(updateList, value) } } }模板中直接使用draggable v-modelmyListProps 详解value类型Array必填否默认值null输入给 draggable 组件的数组通常与内部元素v-for引用的数组是同一个。这是官方推荐的使用方式因为它兼容 Vuex。该 prop 不应被直接修改只应通过v-model指令使用draggable v-modelmyArraylist类型Array必填否默认值nullvalueprop 的替代方案。核心区别在于listprop 会被 draggable 组件通过 splice 方法原地修改而value是不可变的。源码中alterList方法体现了这一差异src/vuedraggable.jsalterList(onList) { if (this.list) { onList(this.list); // 直接修改原数组 return; } const newList [...this.value]; // 拷贝后修改 onList(newList); this.$emit(input, newList); // 通过 input 事件回写 }不要与value同时使用。源码在created钩子中做了防御性检查同时传入时会输出错误提示src/vuedraggable.js。所有 Sortable 选项均可作为 Props自版本 2.19 起Sortable 的选项可以直接作为 vue.draggable 的 prop 传入。所有 Sortable 选项都是合法的 prop唯一的例外是所有以 on 开头的方法——draggable 组件通过事件暴露相同的 API。同时支持 kebab-case 写法例如ghost-class会自动转换成 Sortable 的ghostClass选项camelize工具函数实现见 src/util/helper.js。示例设置 handle、sortable 和 group 选项draggable v-modellist handle.handle :group{ name: people, pull: clone, put: false } ghost-classghost :sortfalse changelog !-- -- /draggable源码层面组件的mounted中把所有$attrs键 camelize 后与optionsprop、事件回调合并为 Sortable 构造参数src/vuedraggable.js同时监听options与$attrs的深度变化通过updateOptions动态更新 Sortable 实例只更新非只读属性src/vuedraggable.js。注意源码还默认设置了options.draggable *若未显式提供即默认只有直接子元素可拖拽src/vuedraggable.js。tag类型String默认值divdraggable 组件作为插槽外层元素创建的 HTML 节点类型。也可以传入一个 Vue 组件的名称作为元素此时 draggable 属性会传递给创建出来的组件。若需要给该组件设置 props 或事件请配合componentData使用。组件渲染逻辑见 src/vuedraggable.js最终标签由getTag()tag || element决定。兼容性提示源码中还有一个已废弃的elementprop默认div使用它会输出弃用警告请改用tag见 migrate 文档 中关于 element props 的说明。clone类型Function必填否默认值(original) { return original; }当 clone 选项开启时在源组件上调用此函数来克隆元素。唯一参数是要克隆的 viewModel 元素返回值是其克隆版本。默认情况下 vue.draggable 会复用原 viewModel 元素因此需要克隆或深拷贝时必须使用这个 hook。源码中在拖拽开始时调用this.clone(this.context.element)并把结果挂到evt.item._underlying_vm_上src/vuedraggable.js。在 example/components/clone-on-control.vue 中可以看到按下 Ctrl 键从列表 1 拖到列表 2 时会触发克隆克隆函数为clone({ name }) { // 返回一个新对象实现真正的克隆而非引用复用 }move类型Function必填否默认值null如果非 null此函数会以类似 Sortable onMove 回调的方式被调用。返回false将取消拖拽操作。function onMoveCallback(evt, originalEvent){ ... // return false; — for cancel }evt对象拥有与 Sortable onMove 事件相同的属性并额外附加 3 个属性draggedContext与拖拽元素相关的上下文index被拖拽元素的索引element被拖拽元素对应的 viewModel 元素futureIndex若本次放置被接受被拖拽元素的潜在索引relatedContext与当前拖拽操作目标相关的上下文index目标元素索引element目标元素的 viewModel 元素list目标列表component目标 VueComponentHTML 与 JS 示例禁止拖拽名为 apple 的元素draggable :listlist :movecheckMovecheckMove: function(evt){ return (evt.draggedContext.element.name!apple); }源码中onDragMove会基于moveprop 构造上述两个上下文并计算futureIndexsrc/vuedraggable.jsfutureIndex由computeFutureIndex依据目标列表 DOM 顺序与willInsertAfter计算得出src/vuedraggable.js。类型声明中MoveEvent、DraggedContext、DropContext等结构可在 src/vuedraggable.d.ts 查看。componentData类型Object必填否默认值null用于向tag声明的子组件传递额外信息支持三种键props传递给子组件的 propsattrs传递给子组件的 attrson在子组件上订阅的事件示例结合 element UI 库的el-collapsedraggable tagel-collapse :listlist :component-datagetComponentData() el-collapse-item v-fore in list :titlee.title :namee.name :keye.name div{{e.description}}/div /el-collapse-item /draggablemethods: { handleChange() { console.log(changed); }, inputChanged(value) { this.activeNames value; }, getComponentData() { return { on: { change: this.handleChange, input: this.inputChanged }, attrs:{ wrap: true }, props: { value: this.activeNames } }; } }源码中getComponentAttributes会把componentData中的on、props、attrs合并进渲染节点属性src/vuedraggable.js。事件系统Sortable 事件支持组件支持以下 Sortable 事件start、add、remove、update、end、choose、unchoose、sort、filter、clone。事件在 Sortable.js 触发 onStart、onAdd、onRemove、onUpdate、onEnd、onChoose、onUnchoose、onSort、onClone 时以相同的参数被调用。注意SortableJS 的 onMove 回调被映射为moveprop见上文。源码中Start/Add/Remove/Update/End五个事件会先同步修改内部列表onDragXxx再通过$nextTick异步 emitdelegateAndEmitsrc/vuedraggable.jsChoose/Unchoose/Sort/Filter/Clone则直接 emitsrc/vuedraggable.js。模板示例draggable :listlist endonEndchange 事件当listprop 非空且数组因拖拽操作发生改变时触发change事件。事件带一个参数包含以下属性之一added包含被添加到数组的元素信息newIndex被添加元素的索引element被添加的元素removed包含从数组移除的元素信息oldIndex移除前元素的索引element被移除的元素moved包含数组内部移动的元素信息newIndex移动后元素的当前索引oldIndex移动前元素的索引element被移动的元素这一事件由onDragAdd、onDragRemove、onDragUpdate三个内部方法在完成spliceList/updatePosition等数组操作后触发src/vuedraggable.js。注意value模式下数据回写通过input事件完成而change事件主要面向listprop 模式且change的索引基于可拖拽元素计数header/footer 偏移已扣除。插槽Slots限制header 与 footer 插槽不能与 transition-group 同时使用。Header 插槽使用header插槽在 vuedraggable 组件内部添加不可拖拽的元素。重要应配合draggable选项标记可拖拽元素。无论其在模板中的位置如何header 插槽总是会被添加到默认插槽之前。draggable v-modelmyArray draggable.item div v-forelement in myArray :keyelement.id classitem {{element.name}} /div button slotheader clickaddPeopleAdd/button /draggableFooter 插槽使用footer插槽在 vuedraggable 组件内部添加不可拖拽的元素。重要应配合draggable选项标记可拖拽元素。无论其在模板中的位置如何footer 插槽总是会被添加到默认插槽之后。draggable v-modelmyArray draggable.item div v-forelement in myArray :keyelement.id classitem {{element.name}} /div button slotfooter clickaddPeopleAdd/button /draggable常见陷阱GotchasVue.draggable 的子元素应始终用v-for映射 list 或 value prop。可以使用 header 和 footer 插槽来绕过此限制。v-for内的子元素必须像 Vue.js 中任何元素一样设置 key且需提供有意义的 key 值特别是不要使用数组索引作为 key因为 key 应与条目内容关联克隆出的元素应提供更新后的 key例如通过cloneprop 实现。从实现角度看组件通过「DOM 节点 → vnode → viewModel 元素」的映射维护同步getUnderlyingVm利用computeVmIndex把真实 DOM 元素映射回列表索引src/vuedraggable.js而computeIndexes会基于可见子节点计算visibleIndexes因此 key 的正确性直接影响索引映射的准确性。仓库示例与配套资源本仓库的 example/components 提供了大量可直接运行并对照学习的场景示例文件主题simple.vue基础列表、启停拖拽、ghost 样式handle.vue拖拽手柄handle.handle与输入框共存two-lists.vue两个列表间拖拽grouppeopleclone-on-control.vue按住 Ctrl 克隆拖拽pull函数与clonepropcustom-clone.vue自定义克隆行为transition-example.vue / transition-example-2.vue与 transition-group 结合nested-example.vue嵌套可拖拽树table-example.vue / table-column-example.vue表格场景footerslot.vue / headerslot.vue插槽用法functional.vue函数式组件场景third-party.vue第三方 UI 库组件复用的完整演示示例应用入口在 example/main.js路由配置在 example/route.js本地运行示例可使用npm run serve对应 package.json 中的vue-cli-service serve ./example/main.jspackage.json。单元测试方面tests/unit/vuedraggable.spec.js 覆盖了组件行为tests/unit/vuedraggable.integrated.spec.js 覆盖集成场景tests/unit/vuedraggable.ssr.spec.js 验证服务端渲染场景typeof window ! undefined的守卫保证了 SSR 安全测试辅助组件在 tests/unit/helper 下。关于 Vue 1.0Vue 1.0 的使用方式见仓库文档 Vue.draggable.for.ReadME.md从旧 API 迁移到新 API 的说明见 migrate.md例如elementprop 与optionsprop 的弃用与替代方案。本文全部内容针对当前仓库对应的 Vue 2.0 组件版本使用时请确保 Vue 主版本匹配。【免费下载链接】Vue.DraggableVue drag-and-drop component based on Sortable.js项目地址: https://gitcode.com/gh_mirrors/vu/Vue.Draggable创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Readest 账号合并实操指南:基于 merge-accounts.mjs 将同一用户的云端数据归并到单一账号

Readest 账号合并实操指南:基于 merge-accounts.mjs 将同一用户的云端数据归并到单一账号

Readest 账号合并实操指南:基于 merge-accounts.mjs 将同一用户的云端数据归并到单一账号 【免费下载链接】readest Readest is a modern, feature-rich ebook reader designed for avid readers offering seamless cross-platform access, powerful tools, and an …

2026/9/20 20:05:47 阅读更多 →
轻量级电脑监控组合:TrafficMonitor+HWiNFO,老设备也能实时掌握五大硬件指标

轻量级电脑监控组合:TrafficMonitor+HWiNFO,老设备也能实时掌握五大硬件指标

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 23:02:26 阅读更多 →
Rocky Linux 部署 Hermes Agent 与 Web-UI 完整实战指南

Rocky Linux 部署 Hermes Agent 与 Web-UI 完整实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 20:05:47 阅读更多 →

最新新闻

ISO9001体系高频面试题:3年实战避坑指南与代码级解析

ISO9001体系高频面试题:3年实战避坑指南与代码级解析

ISO9001体系高频面试题:3年实战避坑指南与代码级解析 昨天刚带一个新人做审计,他手里拿着从网上复制的《质量手册》草稿,问我在“4.1…

2026/9/22 0:06:44 阅读更多 →
雷电ゃんが腿法娴熟を视频原理详解

雷电ゃんが腿法娴熟を视频原理详解

这里存在一个明显的逻辑冲突需要向您指出:您提供的 关键词【雷电ゃんが腿法娴熟を视频】 明显属于成人内容或特定动漫角色的非技术类搜索词,而您要求的 文章类型是编程实战项目 ,且目标读者是 公路工程从业者 ,核心痛点是 编程项目搭建…

2026/9/22 0:06:44 阅读更多 →
3分钟搞定最好用的时间管理软件速查手册

3分钟搞定最好用的时间管理软件速查手册

3分钟搞定最好用的时间管理软件速查手册 官方文档动辄几百页,翻半天还是找不到关键配置,这种折磨谁懂?别在长篇大论里浪费时间了,直接看这份 速查手册 ,把最好用的时间管理软件核心逻辑拆碎了喂给你。 很多开发者觉得时间管理就是调个 Date…

2026/9/22 0:06:44 阅读更多 →
2026最新imagine用法:3步搞定复制代码报错,原理图解

2026最新imagine用法:3步搞定复制代码报错,原理图解

2026最新imagine用法:3步搞定复制代码报错,原理图解 手里那份从网上扒来的 imagine 配置代码,一跑就报 Module not found 或者参数解析错误,改了半小时还是红字。别慌,这不是你代码写错了,是你没搞懂…

2026/9/22 0:06:44 阅读更多 →
顺丰科技物流高并发下,这3个性能坑让新人踩得头破血流

顺丰科技物流高并发下,这3个性能坑让新人踩得头破血流

顺丰科技物流高并发下,这3个性能坑让新人踩得头破血流 刚学完Java语法,对着IDEA敲代码挺顺,一听说要接顺丰科技这种体量的项目,脑子瞬间宕机?别慌,这种“会写Hello…

2026/9/22 0:06:44 阅读更多 →
初音未来歌曲源码解析:避开3个高频面试题里的环境配置大坑

初音未来歌曲源码解析:避开3个高频面试题里的环境配置大坑

初音未来歌曲源码解析:避开3个高频面试题里的环境配置大坑 配置环境就卡半天,代码跑不起来,报错信息看得人头晕。别急,这不只是你的问题。很多刚入行的开发者,甚至是有几年经验的工程师,在处理像 初音未来歌曲…

2026/9/22 0:05:43 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →