基于vue3实现从div文本列表中,拖拽复制到另一个div的tree的节点下,并且在这个节点下可以更换排序,不能把节点下的列表拖拽到外面的结点下
时间: 2024-02-01 12:15:01 浏览: 145
实现这个功能需要用到Vue3的一些指令和事件处理机制。以下是一个简单的实现思路:
1. 定义两个div,一个用来显示文本列表,一个用来显示tree节点。
2. 在文本列表div中,使用v-for指令渲染文本列表。同时,给每个文本元素添加draggable属性,使其可以被拖拽。
3. 在tree节点div中,使用递归组件渲染节点树。每个节点都是一个独立的组件,需要接收一个props用来表示节点的信息。
4. 在每个节点组件中,使用v-if指令判断该节点是否有子节点。如果有,则渲染子节点组件。
5. 给每个节点组件添加一个droppable属性,使其可以接收被拖拽的元素。
6. 监听文本元素的dragstart事件,在事件处理函数中保存被拖拽的元素的信息。
7. 监听节点组件的dragover事件,在事件处理函数中阻止默认行为,并添加一个dragover样式类。
8. 监听节点组件的dragleave事件,在事件处理函数中移除dragover样式类。
9. 监听节点组件的drop事件,在事件处理函数中获取被拖拽的元素信息,并将其添加到目标节点的子节点中。
10. 在节点组件中,使用v-for指令渲染子节点,并给每个子节点添加一个draggable属性和一个dragstart事件处理函数,使其可以被拖拽。
11. 监听节点组件的dragover事件,在事件处理函数中阻止默认行为,并添加一个dragover样式类。
12. 监听节点组件的dragleave事件,在事件处理函数中移除dragover样式类。
13. 监听节点组件的drop事件,在事件处理函数中获取被拖拽的元素信息,并将其添加到目标节点的前面或后面,实现节点排序的功能。
14. 最后,要注意不能将节点拖拽到自己或自己的子节点下。
代码示例:
```
<template>
<div>
<div class="text-list">
<div v-for="text in textList" :key="text.id" :draggable="true" @dragstart="onDragStart(text)">
{{ text.content }}
</div>
</div>
<div class="tree">
<TreeNode v-for="node in treeData" :key="node.id" :node="node"></TreeNode>
</div>
</div>
</template>
<script>
import TreeNode from './TreeNode.vue'
export default {
components: {
TreeNode
},
data() {
return {
textList: [
{ id: 1, content: 'text 1' },
{ id: 2, content: 'text 2' },
{ id: 3, content: 'text 3' }
],
treeData: [
{
id: 1,
name: 'node 1',
children: [
{ id: 2, name: 'node 2', children: [] },
{ id: 3, name: 'node 3', children: [] }
]
},
{
id: 4,
name: 'node 4',
children: [
{ id: 5, name: 'node 5', children: [] },
{ id: 6, name: 'node 6', children: [] }
]
}
],
draggedItem: null,
dropTarget: null
}
},
methods: {
onDragStart(item) {
this.draggedItem = item
},
onDragOver(event, node) {
event.preventDefault()
this.dropTarget = node
node.isDragOver = true
},
onDragLeave(node) {
node.isDragOver = false
},
onDrop(event, node) {
event.preventDefault()
if (node === this.draggedItem || this.isDescendant(node, this.draggedItem)) {
return
}
if (this.dropTarget) {
const index = this.dropTarget.children.indexOf(node)
this.dropTarget.children.splice(index, 0, this.draggedItem)
} else {
const index = this.treeData.indexOf(node)
this.treeData.splice(index, 0, this.draggedItem)
}
this.draggedItem = null
this.dropTarget = null
},
onChildDragStart(item) {
this.draggedItem = item
},
onChildDragOver(event, node) {
event.preventDefault()
this.dropTarget = node
node.isDragOver = true
},
onChildDragLeave(node) {
node.isDragOver = false
},
onChildDrop(event, node) {
event.preventDefault()
if (node === this.draggedItem || this.isDescendant(node, this.draggedItem)) {
return
}
const index = this.dropTarget.parent.children.indexOf(node)
if (index !== -1) {
this.dropTarget.parent.children.splice(index, 0, this.draggedItem)
} else {
this.dropTarget.parent.children.push(this.draggedItem)
}
this.draggedItem = null
this.dropTarget = null
},
isDescendant(node, target) {
if (node.children.length === 0) {
return false
}
for (let i = 0; i < node.children.length; i++) {
if (node.children[i] === target) {
return true
}
if (this.isDescendant(node.children[i], target)) {
return true
}
}
return false
}
}
}
</script>
```
TreeNode组件代码示例:
```
<template>
<div class="node" :class="{ 'drag-over': isDragOver }" :droppable="true" @dragover="onDragOver($event, node)" @dragleave="onDragLeave(node)" @drop="onDrop($event, node)">
<div class="name" :draggable="true" @dragstart="onDragStart(node)">
{{ node.name }}
</div>
<div class="children">
<TreeNode v-for="child in node.children" :key="child.id" :node="child" @child-dragstart="onChildDragStart(child)" @child-dragover="onChildDragOver($event, child)" @child-dragleave="onChildDragLeave(child)" @child-drop="onChildDrop($event, child)"></TreeNode>
</div>
</div>
</template>
<script>
export default {
props: {
node: {
type: Object,
required: true
}
},
data() {
return {
isDragOver: false
}
},
methods: {
onDragStart(node) {
this.$emit('child-dragstart', node)
},
onDragOver(event, node) {
this.$emit('child-dragover', event, node)
},
onDragLeave(node) {
this.$emit('child-dragleave', node)
},
onDrop(event, node) {
this.$emit('child-drop', event, node)
this.isDragOver = false
},
onChildDragStart(node) {
this.$emit('child-dragstart', node)
},
onChildDragOver(event, node) {
this.$emit('child-dragover', event, node)
},
onChildDragLeave(node) {
this.$emit('child-dragleave', node)
},
onChildDrop(event, node) {
this.$emit('child-drop', event, node)
this.isDragOver = false
}
}
}
</script>
```
阅读全文