安装依赖
npm
npm install vuedraggable@next
引入组件
vue
import draggable from 'vuedraggable'
基础用法
vue
<template>
<draggable v-model="innerList" item-key="props" handle=".sort-icon" :disabled="false" :animation="300">
<template #item="{ element }">
<div class="flexAlign">
<div class="sort-icon" style="margin-right: 5px;cursor: pointer;font-size: 18px;">⠿</div>
{{ element.label }}
</div>
</template>
</draggable>
</template>
<script setup>
import draggable from 'vuedraggable';
const innerList = ref([
{label:"名称"}
])
</script>
常用属性说明
| 属性名 | 类型 | 说明 |
|---|---|---|
v-model |
Array | 绑定数组,拖拽后自动更新顺序 |
item-key |
String | 每个 item 的唯一 key |
tag |
String | 渲染的容器标签,默认div |
group |
String/Object | 分组设置,支持跨列表拖拽 |
disabled |
Boolean | 是否禁用拖拽 |
handle |
String | 拖拽手柄选择器 |
animation |
Number | 拖拽的动画过渡时间 |
事件名
| 事件名 | 说明 | 参数 |
|---|---|---|
@start |
拖拽开始 | event |
@end |
拖拽完成 | event |
@change |
列表顺序发生变化 | { moved: { oldIndex, newIndex } } |
@add |
从别的列表添加到当前 | event |
@remove |
当前列表被移除元素 | event |
实战进阶场景
拖拽手柄限制(只能通过图标拖动)
xml
<draggable v-model="list" item-key="id" handle=".sort-icon">
<template #item="{ element }">
<div>
<span class="sort-icon">⠿</span>
{{ element.name }}
</div>
</template>
</draggable>
禁用某项拖动
xml
<draggable v-model="list" item-key="id" :move="checkMove" @change="logChange">
</draggable>
<script setup>
const checkMove = (e) => {
return !e.draggedContext.element.fixed
}
const logChange = (e) => console.log(e)
</script>
跨列表拖拽
ini
<draggable v-model="list1" item-key="id" group="all">
...
</draggable>
<draggable v-model="list2" item-key="id" group="all">
...
</draggable>
也可以使用对象方式更灵活控制:
yaml
group="{ name: 'all', pull: true, put: true }"
嵌套拖拽(如树形结构)
ini
<draggable v-model="tabList" item-key="id">
<template #item="{ element }">
<div>{{ element.name }}</div>
<draggable
v-if="element.children"
v-model="element.children"
item-key="id"
:group="{ name: 'all' }"
>
<template #item="{ element }">
<div class="child">{{ element.name }}</div>
</template>
</draggable>
</template>
</draggable>
示例:拖拽后保存顺序
xml
<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>
常见问题排查
-
拖不动?
- 是否设置了
item-key - 是否被 CSS 覆盖了事件(例如 overflow、position)
- 是否启用了
disabled属性
- 是否设置了
-
拖动异常(闪烁/跳动)?
- 确保子项具有稳定的
key - 不要在拖拽中操作 DOM
- 确保子项具有稳定的
-
样式塌陷?
- 添加必要的
min-height、border保持布局正常
- 添加必要的