Vue3中使用vuedraggable实现拖拽排序与高级交互

vuedraggable​ 是 Vue 社区中广泛使用的拖拽排序组件,基于强大的 SortableJS 库,支持拖拽排序、跨列表拖拽、嵌套结构、拖拽手柄等复杂交互。

本文将系统讲解 vuedraggable​ 在 Vue 3 项目中的使用,包括基础使用、常见场景与实战技巧。


📦 安装与引入

安装依赖(Vue 3 需使用 next​ 版本):

npm install vuedraggable@next
# 或者使用 yarn
yarn add vuedraggable@next

引入组件(适用于 <script setup>​):

import draggable from 'vuedraggable'

✨ 基础用法

拖拽列表并保持同步顺序

<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

📚 实战进阶场景

✅ 拖拽手柄限制(只能通过图标拖动)

<draggable v-model="list" item-key="id" handle=".drag-icon">
  <template #item="{ element }">
    <div>
      <span class="drag-icon">⠿</span>
      {{ element.name }}
    </div>
  </template>
</draggable>

✅ 禁用某项拖动

<draggable v-model="list" item-key="id" :move="checkMove" @change="logChange">
</draggable>

<script setup>
const checkMove = (evt) => {
  return !evt.draggedContext.element.fixed
}
const logChange = (e) => console.log(e)
</script>

✅ 跨列表拖拽

<draggable v-model="listA" item-key="id" group="shared">
  ...
</draggable>

<draggable v-model="listB" item-key="id" group="shared">
  ...
</draggable>

也可以使用对象方式更灵活控制:

group="{ name: 'shared', pull: true, put: true }"

✅ 嵌套拖拽(如树形结构)

<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>

🧪 示例:拖拽后保存顺序

<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​ 保持布局正常

🔗 官方资源


🧵 小结

vuedraggable​ 是 Vue 3 项目中实现交互式拖拽的首选利器。通过合理运用它的 group​、handle​、事件和嵌套能力,可以覆盖几乎所有业务场景中的排序与拖拽需求。

posted @ 2025-07-20 13:11  李东阳  阅读(4558)  评论(0)    收藏  举报