
vuedraggable 拖拽排序组件实战指南
`vuedraggable` 是 Vue 社区中广泛使用的拖拽排序组件,基于强大的SortableJS库,支持拖拽排序、跨列表拖拽、嵌套结构、拖拽手柄等复杂交互。本文系统讲解 `vuedraggable` 在 Vue 3 项目中的使用,包括安装引入、基础用法、常用属性、常见事件、实战进阶场景与问题排查。
目录
一、安装与引入
1. 安装依赖
2. 引入组件
二、基础用法
拖拽列表并保持同步顺序
三、常用属性说明
四、常见事件
五、实战进阶场景
1. 拖拽手柄限制(只能通过图标拖动)
2. 禁用某项拖动
3. 跨列表拖拽
4. 嵌套拖拽(树形结构)
5. 示例:拖拽后保存顺序
六、常见问题排查
七、官方资源
八、小结
vuedraggable是 Vue 社区中广泛使用的拖拽排序组件,基于强大的 SortableJS 库,支持拖拽排序、跨列表拖拽、嵌套结构、拖拽手柄等复杂交互。本文系统讲解vuedraggable在 Vue 3 项目中的使用,包括安装引入、基础用法、常用属性、常见事件、实战进阶场景与问题排查。
一、安装与引入
1. 安装依赖
注意:Vue 3 项目需使用
next版本。
bash
npm install vuedraggable@next
# 或者使用 yarn
yarn add vuedraggable@next
2. 引入组件
适用于 <script setup> 语法:
ts
import draggable from 'vuedraggable'
二、基础用法
拖拽列表并保持同步顺序
v-model 绑定数组,拖拽后会自动更新顺序;item-key 指定每个 item 的唯一 key,通过 #item 插槽渲染每一项。
vue
<template>
<draggable v-model="list" item-key="id">
<template #item="{ element }">
<div class="item">{{ element.name }}</div>
</template>
</draggable>
</template>
<script setup>
import { ref } from 'vue'
import draggable from 'vuedraggable'
const list = ref([
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' }
])
</script>
<style scoped>
.item {
padding: 10px;
margin-bottom: 5px;
background: #f9f9f9;
border: 1px solid #ddd;
}
</style>
三、常用属性说明
| 属性名 | 类型 | 说明 |
|---|---|---|
v-model |
Array | 绑定数组,拖拽后自动更新顺序 |
item-key |
String | 每个 item 的唯一 key |
tag |
String | 渲染的容器标签,默认 div |
group |
String/Object | 分组设置,支持跨列表拖拽 |
disabled |
Boolean | 是否禁用拖拽 |
handle |
String | 拖拽手柄选择器 |
四、常见事件
| 事件名 | 说明 | 参数 |
|---|---|---|
@start |
拖拽开始 | event |
@end |
拖拽完成 | event |
@change |
列表顺序发生变化 | { moved: { oldIndex, newIndex } } |
@add |
从别的列表添加到当前 | event |
@remove |
当前列表被移除元素 | event |
五、实战进阶场景
1. 拖拽手柄限制(只能通过图标拖动)
通过 handle 属性指定手柄选择器,只有拖动手柄图标才能触发拖拽:
vue
<draggable v-model="list" item-key="id" handle=".drag-icon">
<template #item="{ element }">
<div>
<span class="drag-icon">⠿</span>
{{ element.name }}
</div>
</template>
</draggable>
2. 禁用某项拖动
通过 :move 回调拦截拖拽,结合元素标记决定是否允许移动:
vue
<draggable v-model="list" item-key="id" :move="checkMove" @change="logChange">
</draggable>
<script setup>
const checkMove = (evt) => {
return !evt.draggedContext.element.fixed // fixed 为 true 的项不允许拖动
}
const logChange = (e) => console.log(e)
</script>
3. 跨列表拖拽
使用相同的 group 名称即可在两个列表间拖拽:
vue
<draggable v-model="listA" item-key="id" group="shared">
...
</draggable>
<draggable v-model="listB" item-key="id" group="shared">
...
</draggable>
也可以使用对象方式更灵活地控制:
vue
group="{ name: 'shared', pull: true, put: true }"
4. 嵌套拖拽(树形结构)
递归渲染子列表,实现树形结构的多层拖拽:
vue
<draggable v-model="tree" item-key="id">
<template #item="{ element }">
<div>{{ element.name }}</div>
<draggable
v-if="element.children"
v-model="element.children"
item-key="id"
:group="{ name: 'nested' }"
>
<template #item="{ element }">
<div class="child">{{ element.name }}</div>
</template>
</draggable>
</template>
</draggable>
5. 示例:拖拽后保存顺序
在拖拽结束后将最新顺序提交保存:
vue
<el-button @click="save">保存顺序</el-button>
<draggable v-model="list" item-key="id" @end="save" />
<script setup>
const save = () => {
console.log('新顺序:', list.value.map(i => i.id))
}
</script>
六、常见问题排查
1. 拖不动?
- 是否设置了
item-key - 是否被 CSS 覆盖了事件(例如
overflow、position) - 是否启用了
disabled属性
2. 拖动异常(闪烁/跳动)?
- 确保子项具有稳定的
key - 不要在拖拽中操作 DOM
3. 样式塌陷?
- 添加必要的
min-height、border保持布局正常
七、官方资源
- GitHub:vue.draggable.next
- SortableJS 文档:https://sortablejs.github.io/Sortable/
八、小结
vuedraggable 是 Vue 3 项目中实现交互式拖拽的首选利器。通过合理运用它的 group、handle、事件和嵌套能力,可以覆盖几乎所有业务场景中的排序与拖拽需求。