当前位置: 首页 > backend >正文

vue2使用el-tree实现两棵树间节点的拖拽复制

原文链接:两棵el-tree的节点跨树拖拽实现

参照这篇文章,把它做成组件,新增左侧树(可拖出)被拖节点变灰提示;

拖拽中
在这里插入图片描述
拖拽后
在这里插入图片描述
TreeDragComponent.vue

<template><!-- 两棵el-tree的节点跨树拖拽实现 --><div class="tree-drag"><!-- 左侧树(可拖出) --><el-tree:data="treeData1"ref="tree1"class="tree" node-key="id"draggabledefault-expand-all:allow-drop="returnFalse":props="defaultProps"@node-drag-start="handleDragstart"@node-drag-end="handleDragend"><!-- 使用作用域插槽自定义节点样式 --><span slot-scope="{ node, data }" :class="{ 'custom-red': data.isHighlighted }">{{ node.label }}</span></el-tree><!-- 右侧树(可拖入) --><el-tree:data="treeData2" ref="tree2"class="tree" node-key="id"draggabledefault-expand-all:props="defaultProps":allow-drop="returnTrue"></el-tree></div>
</template><script>
export default {
name: "TreeDrag",
props:['treeData1','treeData2'],
data() {return {defaultProps: {children: 'children',label: 'name'},};
},
methods: {// (1) 手动触发:该节点向父组件通知拖拽开始(只不过目标树是右侧树)// 经过这个移花接木的操作,右侧的树会误以为是自身的节点触发了tree-node-drag-start事件,它会将被拖拽节点保存在组件内handleDragstart (node, event) {this.$refs.tree2.$emit('tree-node-drag-start', event, {node: node});},// (2) 鼠标滑过阶段// 当鼠标拖拽着左侧树上的节点从右侧树上的节点划过(也就是触发dragover事件)时,右侧树会误以为是在拖拽自己的节点,因此会在tree-node-drag-over事件中自动执行位置计算,所以这一阶段无需我们干预。// (3)鼠标释放阶段// 尽管此时右侧树已经误以为被拖拽的是自身节点,但被拖拽的节点此时仍然是左侧树的子组件,所以当鼠标释放时,它只能向左侧树(即它的父组件)触发tree-node-drag-end事件。由于左侧树不允许释放,所以此时节点并没有发生移动。// 为了让右侧树收到鼠标释放的通知,我们开始进行第二次移花接木,即把左侧树上发生的tree-node-drag-end事件以同样的方式触发给右侧树handleDragend (draggingNode, endNode, position, event) {//不只是做节点移动,而是拖拽复制,也就是要保留左侧树上的原节点//真正要保留原节点很难实现,所以选择在移动后恢复左侧树上的节点// 插入一个空节点用于占位let emptyData = {id: (+new Date), children: []};this.$refs.tree1.insertBefore(emptyData, draggingNode);this.$refs.tree2.$emit('tree-node-drag-end', event);this.$nextTick(() => {// 如果是移动到了当前树上,需要清掉空节点if (this.$refs.tree1.getNode(draggingNode.data)) {this.$refs.tree1.remove(emptyData);} else {// 如果移动到了别的树上,需要恢复该节点,并清掉空节点let data = JSON.parse(JSON.stringify(draggingNode.data));this.createHighlightedNode(data); // 添加标记字段this.$refs.tree1.insertAfter(data, this.$refs.tree1.getNode(emptyData));this.$refs.tree1.remove(emptyData);}})},// 递归创建带高亮标记的节点createHighlightedNode(data) {// 给当前节点添加 isHighlighted 属性data.isHighlighted = true;// 检查是否有子节点if (data.children && Array.isArray(data.children)) {// 递归处理每个子节点data.children.forEach(child => {this.createHighlightedNode(child);});}return data;},// 允许内部拖拽returnTrue () {// 可传参数:draggingNode, dropNode, type// 校验所有拖拽节点是否允许放入(如只能放入同级或特定父级)// return this.draggingNodes.every(node => //     node.level <= 2 &&  // 限制最大层级//     node.type !== 'system'  // 限制类型// )return true;},// 禁止内部拖拽returnFalse () {return false;}
}
};
</script><style lang="scss" scoped>
.tree-drag {display: flex;justify-content: space-between;.tree {flex-grow: 1;.custom-red {color: #E4E4E4 !important; /* 红色背景 */font-size: 14px !important;}}}
</style>

Parent.vue

<TreeDrag :treeData1="treeDataLeft" :treeData2="treeDataRight"></TreeDrag>

element-ui源码中用于定义树节点的element-ui\packages\tree\src\tree-node.vue组件
在这里插入图片描述

下一篇:在此基础上加功能,el-tree拖拽事件,限制同级拖拽,获取拖拽后节点的前后节点,同级拖拽合并父节点name且子节点加入目标节点里

http://www.xdnf.cn/news/9238.html

相关文章:

  • LeetCode 2894.分类求和并作差:数学O(1)一行解决
  • Java提取markdown中的表格
  • go并发与锁之sync.Mutex入门
  • 国11阶乘约数-质因数分解
  • C/C++的OpenCV的锐化
  • vue 前端请求跨域解决办法
  • 九级融智台阶与五大要素协同的量子化解析
  • MGAug:图像变形潜空间中的多模态几何增强|文献速递-深度学习医疗AI最新文献
  • 端口 3389 服务 ms - wbt - server 漏洞修复方法
  • 你的网站真的安全吗?如何防止网站被攻击?
  • 联软科技统一安全工作空间:零信任架构下的远程办公数据安全守护者
  • 每天掌握一个Linux命令 - sqlite3
  • EasyRTC嵌入式SDK音视频实时通话助力WebRTC技术与智能硬件协同发展
  • Nginx 配置文件深度解析:从核心模块到扩展机制
  • WPF【11_4】WPF实战-重构与美化(MVVM 架构)
  • 【elasticsearch 7 或8 的安装及配置SSL 操作指引】
  • 【Doris入门】Doris初识:分布式分析型数据库的核心价值与架构解析
  • 关于空调温度控制仿真模型的详细技术文档,包含数学模型、Python实现和系统分析
  • 引导者之歌------------嵌入式软件面试问题集成
  • 修改SpringBootApplication类的入参后,引用外部yml的启动命令要修改
  • ArcGIS Pro 3.4 二次开发 - 地理处理
  • 计算机网络练习题
  • 自动生成提示技术突破:AUTOPROMPT重塑语言模型应用
  • Java+Playwright自动化-2-环境准备与搭建-基于Maven
  • Jenkins实践(9):pipeline构建历史展示包名和各阶段间传递参数
  • C++:设计模式--工厂模式
  • linux安装MYSQL
  • 图论学习笔记 5 - 最小树形图
  • leetcode hot100刷题日记——22.只出现一次的数字
  • Python安装、pycharm配置和添加库下载