vuedraggable-拖拽插件使用小计

1、安装插件

Vue2

npm i vuedraggable@2 # 或 yarn add vuedraggable

Vue3(官方仓库改名 vue.draggable.next)

npm i vuedraggable@next # 或 yarn add vuedraggable@next

CDN(测试用)
cdn.jsdelivr.net/npm/vuedrag...
cdn.jsdelivr.net/npm/vuedrag...

2、注册组件

全局注册(main.js)

import draggable from 'vuedraggable' // Vue3 把包名改成 'vuedraggable-next'

app.component('draggable', draggable)

局部注册

import draggable from 'vuedraggable'

export default { components:{ draggable } }

3、最小可运行示例

Vue2 写法

js 复制代码
<template>
  <draggable v-model="list" class="drag-area">
    <div v-for="item in list" :key="item.id">{{ item.name }}</div>
  </draggable>
</template>
<script>
import draggable from 'vuedraggable'
export default {
  components:{ draggable },
  data(){ return { list:[{id:1,name:'A'},{id:2,name:'B'}] } }
}
</script>

Vue3 写法(必须具名插槽 item,且只能一个根节点)

vue 复制代码
<template>
  <draggable v-model="list" item-key="id">
    <template #item="{ element }">
      <div class="drag-area__item">{{ element.name }}</div>
    </template>
  </draggable>
</template>

<script setup>
import draggable from 'vuedraggable-next'
import { reactive } from 'vue'
const list = reactive([ {id:1,name:'A'}, {id:2,name:'B'} ])
</script>

4、核心 Props 详解

属性 类型 默认值 说明
v-model / list Array [] 与视图同步的数据源;list 与 v-model 不可同时出现
item-key String Vue3 必填,提供列表 key
tag String 'div' 容器节点名
handle String '' 仅当匹配选择器时才允许拖动,如 handle=".drag-handle"
group String / Object '' 跨列表拖拽,如 group="shared" 或 :group="{name:'shared', pull:'clone', put:true}"
animation Number 150 排序动画时长(ms)
ghost-class String 'sortable-ghost' 占位元素样式
drag-class String 'sortable-drag' 正在拖拽元素样式
filter String '' 禁止拖动的选择器
disabled Boolean false 禁用拖拽
move Function null 返回 false 取消本次拖动
clone Function original=>original 跨列表 pull='clone' 时,控制克隆逻辑

5、事件

事件名 回调形参 触发时机
@start evt 开始拖动
@end evt 拖动结束
@change evt 列表数据发生 add / remove / move 时触发
@add evt 接收外部元素
@remove evt 元素被拖到其他列表
@update evt 同列表内部排序
@choose / unchoose evt 选中/取消选中

6、多列表互相拖拽

A、B两个列表可互相拖入,支持克隆:

vue 复制代码
<template>
  <div class="lists">
    <!-- 列表 A -->
    <draggable
      v-model="listA"
      :group="{ name:'shared', pull:'clone', put:true }"
      :clone="deepClone"
    >
      <template #item="{ element }"><div>{{ element.name }}</div></template>
    </draggable>

    <!-- 列表 B -->
    <draggable
      v-model="listB"
      group="shared"
    >
      <template #item="{ element }"><div>{{ element.name }}</div></template>
    </draggable>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
import draggable from 'vuedraggable-next'
const listA = reactive([{id:1, name:'a'}])
const listB = reactive([])
const deepClone = (o) => JSON.parse(JSON.stringify(o))
</script>

注意点:

  • group 的 name 必须相同;
  • 数据结构一致;
  • 数组必须是响应式(Vue2 用 Vue.observable / Vue3 用 reactive、ref)。

7、插槽用法

插槽名 作用域 说明
default - 整个容器内容,可放置不可拖动的 header/footer
item { element, index } Vue3 唯一必填插槽,渲染每一个可拖拽节点
header/footer - 固定区域,不会参与拖拽

示例:在列表顶部增加不可拖动的「添加按钮」

vue 复制代码
<draggable v-model="list">
  <template #header>
    <button @click="add">+ Add</button>
  </template>
  <template #item="{ element }">
    <div>{{ element.name }}</div>
  </template>
</draggable>

8、与UI库混合使用

Element Plus / Ant Design Vue 的表格、卡片、步骤条等均可被 draggable 包裹:

vue 复制代码
<draggable v-model="tableData" item-key="id">
  <template #item="{ element }">
    <el-card>{{ element.title }}</el-card>
  </template>
</draggable>

9、常见问题

  • Vue3 报错 "item slot required" → 使用具名插槽 #item
  • 拖动后视图未更新 → 确认数组是响应式 & key 唯一。
  • 两个列表无法互相拖 → group name 不一致或数据结构不同。
  • 想拖拽表格行 → 使用 <tr> 作为根节点即可(需设置 tag="tbody")。

10、在线资源/官方仓库

官方 Sortable.js 配置表(拖拽行为全部继承):github.com/SortableJS/...

相关推荐
张拭心5 小时前
Cursor 又偷偷更新,这个功能太实用:Visual Editor for Cursor Browser
前端·人工智能
I'm Jie5 小时前
深入了解 Vue 3 组件间通信机制
前端·javascript·vue.js
用户90443816324606 小时前
90%前端都踩过的JS内存黑洞:从《你不知道的JavaScript》解锁底层逻辑与避坑指南
前端·javascript·面试
CodeCraft Studio7 小时前
文档开发组件Aspose 25.12全新发布:多模块更新,继续强化文档、图像与演示处理能力
前端·.net·ppt·aspose·文档转换·word文档开发·文档开发api
PPPPickup7 小时前
easychat项目复盘---获取联系人列表,联系人详细,删除拉黑联系人
java·前端·javascript
老前端的功夫7 小时前
前端高可靠架构:医疗级Web应用的实时通信设计与实践
前端·javascript·vue.js·ubuntu·架构·前端框架
前端大卫8 小时前
【重磅福利】学生认证可免费领取 Gemini 3 Pro 一年
前端·人工智能
孜燃8 小时前
Flutter APP跳转Flutter APP 携带参数
前端·flutter
脾气有点小暴8 小时前
前端页面跳转的核心区别与实战指南
开发语言·前端·javascript
lxh01138 小时前
最长递增子序列
前端·数据结构·算法