vue实现tree拖拽
Vue 实现 Tree 拖拽功能
使用 vuedraggable 库
vuedraggable 是基于 Sortable.js 的 Vue 拖拽组件,适合实现树形结构的拖拽功能。
安装依赖:
npm install vuedraggable
基础实现代码:

<template>
<div>
<draggable
v-model="treeData"
group="nodes"
@end="onDragEnd">
<div v-for="(node, index) in treeData" :key="node.id">
{{ node.name }}
<draggable
v-if="node.children"
v-model="node.children"
group="nodes"
@end="onDragEnd">
<div v-for="child in node.children" :key="child.id">
{{ child.name }}
</div>
</draggable>
</div>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable'
export default {
components: { draggable },
data() {
return {
treeData: [
{
id: 1,
name: 'Node 1',
children: [
{ id: 11, name: 'Child 1' },
{ id: 12, name: 'Child 2' }
]
},
{
id: 2,
name: 'Node 2',
children: [
{ id: 21, name: 'Child 1' }
]
}
]
}
},
methods: {
onDragEnd() {
console.log('拖拽完成', this.treeData)
}
}
}
</script>
使用 Element UI 的 Tree 组件
如果项目中使用 Element UI,可以直接使用其 Tree 组件内置的拖拽功能。
安装 Element UI:

npm install element-ui
实现代码:
<template>
<el-tree
:data="treeData"
draggable
@node-drop="handleDrop"
node-key="id">
</el-tree>
</template>
<script>
export default {
data() {
return {
treeData: [
{
id: 1,
label: 'Node 1',
children: [
{ id: 11, label: 'Child 1' },
{ id: 12, label: 'Child 2' }
]
},
{
id: 2,
label: 'Node 2',
children: [
{ id: 21, label: 'Child 1' }
]
}
]
}
},
methods: {
handleDrop(draggingNode, dropNode, type) {
console.log('拖拽完成', this.treeData)
}
}
}
</script>
自定义实现拖拽逻辑
如果需要更精细的控制,可以手动实现拖拽逻辑。
基础实现思路:
<template>
<div class="tree">
<div
v-for="node in treeData"
:key="node.id"
class="node"
draggable
@dragstart="dragStart(node)"
@dragover.prevent
@drop="drop(node)">
{{ node.name }}
<div
v-if="node.children"
class="children">
<div
v-for="child in node.children"
:key="child.id"
class="child"
draggable
@dragstart="dragStart(child)"
@dragover.prevent
@drop="drop(child)">
{{ child.name }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
treeData: [...], // 树数据
draggedNode: null // 当前拖拽的节点
}
},
methods: {
dragStart(node) {
this.draggedNode = node
},
drop(targetNode) {
// 实现节点移动逻辑
// 需要处理父子关系变更
}
}
}
</script>
<style>
.node, .child {
padding: 8px;
margin: 4px;
border: 1px solid #ddd;
}
.children {
margin-left: 20px;
}
</style>
注意事项
- 树形数据结构需要包含唯一标识符(如 id)
- 拖拽时需要处理父子关系的变更
- 跨层级拖拽时需要更新整个树结构
- 可以考虑添加动画效果提升用户体验
- 复杂场景可能需要实现限制条件(如某些节点不可拖拽)
以上方法可以根据项目需求选择使用,vuedraggable 适合通用场景,Element UI Tree 适合使用该组件库的项目,自定义实现则适合需要高度定制化的场景。






