vue3项目+element树形tree组件实现拖拽功能
·
项目背景: 需要实现树形组件中的内容可以拖拽到功能区的六个功能位,使用tree自带的拖拽draggable功能会产生问题,故而使用HTML5原生拖拽事件来控制实现。
1.首先渲染树形数据
<el-tree
ref="treeRef"
style="max-width: 600px"
class="filter-tree"
:accordion="false"
:show-checkbox="false"
:data="data"
:props="defaultProps"
:filter-node-method="filterNode"
node-key="id"
>
<template #default="{ node, data }">
<div v-if="data.children" class="custom-tree-node">
<span>{{ node.label }}</span>
</div>
<div v-else draggable="true" @dragstart="handleDragStart(data, $event)" class="custom-tree-node flex relative w-full">
<div>{{ node.label }}</div>
</div>
</template>
</el-tree>
开启拖拽 draggable="true",这里使用v-if方法限制只给二级菜单添加了拖拽事件,一级菜单不能拖拽
01. 绑定@dragstart="handleDragStart(data, $event)"事件,给退拽元素打上标签和参数
// 拖拽开始事件
const handleDragStart = (node: Node, ev: any) => {
ev.dataTransfer?.setData('text/plain', node.id.toString()); // 将被拖拽项的 id 存入 dataTransfer 对象中
ev.dataTransfer?.setData('text/type', "tree"); // 将被拖拽项的 type 存入 dataTransfer 对象中
ev.dataTransfer?.setData('text/label', node.label.toString()); // 将被拖拽项的 label 存入 dataTransfer 对象中
};
2.渲染拖拽放置的功能区
<div class="flex w-full h-full" @dragover.prevent="dragoverInfo" @drop="handleDrop">
<div class="w-full flex h-full justify-between flex-wrap">
<div v-for="item in moveBoxList" :key="item.id" :data-id="item.id" class="moveBox w-32.6% h-28.4vh mb-6px mt-6px relative">
<template v-if="item.url">
<div class="w-full h-40px absolute z-9 top-0 left-0 bg-#293A5880 flex justify-between items-center">
<div class="infoTitle ALMM text-(16px #333333)">{{ item.name }}</div>
<div class="text-(14px #ffffff) flex justify-center items-center mr-12px">
<div class="flex justify-center items-center cursor-pointer mr-16px">
<img src="/@/assets/images/playbackIcon.png" alt="">
<span class="ml-8px">回放</span>
</div>
<div class="flex justify-center items-center cursor-pointer">
<img src="/@/assets/images/amplifyIcon.png" alt="">
<span class="ml-8px">放大</span>
</div>
</div>
</div>
<div class="w-full h-full flex bg-#E1E1E1 justify-center items-center" v-loading="item.isLoading">
<img class="w-120px h-130px" src="/@/assets/images/noData.png" alt="">
</div>
</template>
<template v-else>
<div class="w-full h-full flex bg-#E1E1E1 justify-center items-center">
<img class="w-120px h-130px" src="/@/assets/images/noData.png" alt="">
</div>
</template>
</div>
</div>
</div>
给功能区添加@dragover.prevent="dragoverInfo" 和 @drop="handleDrop"事件,
01. dragoverInfo事件允许拖拽放置
// 拖拽
const dragoverInfo = (event) => {
event.preventDefault(); // 允许放置
}
02. handleDrop事件监听拖拽放置结束
// 拖拽进入结束
const handleDrop = (event) => {
event.preventDefault();
const type = event.dataTransfer?.getData('text/type'); // 获取被拖拽项的 id
if (type === "tree") {
const id = event.dataTransfer?.getData('text/plain'); // 获取被拖拽项的 id
const label = event.dataTransfer?.getData('text/label'); // 获取被拖拽项的 id
// 找到被拖拽到的 moveBox 容器
const targetElement = event.target as HTMLElement;
const moveBoxElement = targetElement.closest('.moveBox');
if (moveBoxElement) {
const moveBoxId = parseInt(moveBoxElement.getAttribute('data-id') || '0');
console.log('拖入的 moveBox 是:', moveBoxId);
// 这里可以找到当前拖拽的元素放置在哪一个功能区的位置,然后执行对应的业务逻辑
}
}
}
小结:
1. 通过给树形组件自定义节点绑定允许拖拽事件和配置,通过绑定的拖拽事件给拖拽元素打上标记并且携带参数
2. 在功能区绑定@dragover.prevent事件允许拖拽元素放置
3. 在功能区绑定@drop事件监听拖拽结束,通过业务逻辑找到拖拽到第几个功能区,并且拿取参数执行需要做的业务逻辑
更多推荐


所有评论(0)