Vue3使用vuedraggable实现拖拽排序

安装依赖

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>

常见问题排查

  1. 拖不动?

    • 是否设置了 item-key
    • 是否被 CSS 覆盖了事件(例如 overflow、position)
    • 是否启用了 disabled 属性
  2. 拖动异常(闪烁/跳动)?

    • 确保子项具有稳定的 key
    • 不要在拖拽中操作 DOM
  3. 样式塌陷?

    • 添加必要的 min-heightborder 保持布局正常
相关推荐
LFly_ice几秒前
Next-1-启动!
开发语言·前端·javascript
小时前端3 分钟前
谁说 AI 历史会话必须存后端?IndexedDB方案完美翻盘
前端·agent·indexeddb
wordbaby7 分钟前
TanStack Router 基于文件的路由
前端
wordbaby12 分钟前
TanStack Router 路由概念
前端
wordbaby14 分钟前
TanStack Router 路由匹配
前端
cc蒲公英15 分钟前
vue nextTick和setTimeout区别
前端·javascript·vue.js
程序员刘禹锡20 分钟前
Html中常用的块标签!!!12.16日
前端·html
我血条子呢30 分钟前
【CSS】类似渐变色弯曲border
前端·css
DanyHope31 分钟前
LeetCode 两数之和:从 O (n²) 到 O (n),空间换时间的经典实践
前端·javascript·算法·leetcode·职场和发展
hgz071032 分钟前
企业级多项目部署与Tomcat运维实战
前端·firefox