使用el-tree支持保留源节点的拖放操作

产品的需求千奇百怪,在成长中的产品的需求更是。最怕的是到处抄,然后四不像,苦了开发人员了。

话说我们需要一棵树,这个树上有中间节点(文件夹)和叶子节点。然后这些数据会来自两个系统,代表的含义也不相同,就这样优秀没有办法,这都不是事。事情是支持某些文件夹下的节点(包括子中间节点和叶子节点)能拖放到另外一些节点里面,这也不是事,el-tree能支持。可怕的就是,一些拖放是删除源节点的操作,就像移动操作;另一些拖放是保留源节点的操作,就像在目标节点下创建了副本,哈哈,就是这么有意思:(

删除源的移动是el-tree本来就支持的,我们今天要说的是保留源的拖放。其实我这里能在不修改element-ui源码的情况下实现这个功能真的说算是限制了一些事情,如果跟我的需求不一样的,这种方法还是不能用的,一句话就是场景不符合。我的一些假定:

  1. 只支持inner类型的拖放,如果不知道我在说什么,说明你没来对地方,inner是el-tree支持的三种拖放类型之一,它们是inner、prev、next,意思对,关键字对不对我也不想再去查了,文档上有
  2. 节点是懒加载,即设置了lazy

我的实现方案是,在需要保留源节点的情况下,在node-drag-over事件里面把el-tree实例中的dragState.dropType改成’none’,因为我发现在drop事件里面,会根据dropType来做相应的操作,如果是none,则不会把源节点删除,也不会把源节点插入目标节点。none这个类型是为了处理上面三种类型之外的操作做的,其实就是不做任何的拖放操作,我在实际中模拟出了这种场景,就是把元素拖出去走一圈,然后再回到原位置。

...
handleNodeDragOver(draggingNode, dropNode, type) {
	... // 判断是否要保留源节点,然后才执行下面的语句
	this.$refs.tree.dragState.dropType = 'none';
}
...

如果dropType是node的话,不会触发node-drop事件,这样我们其实是不能知道最后的拖放操作的。那么怎么办呢?虽然没有node-drop事件,但是它会触发node-drag-end事件,只能把逻辑写在这里了,不过要判断是否是需要保留源节点的情况,然后才去做事情。

handleNodeDragEnd(draggingNode, dropNode, type) {
    ... // 判断是否需要保留源节点
    // 巴拉巴拉

}

也就是说drop-node和一部分node-drap-end我都认为是最终的操作了。这里我会调用接口告知后端需要移动节点了,后端会把数据落库,然后我需要在接口返回后重新加载目标节点,其实我并没有都重新加载,我是判断如果目标节点已经展开了才去加载,否则还让它保持collapse状态,也就是啥也不动。

好了实现思路也就是这样,现在为止基本满足了需求,项目还在开发中,后面如果遇到了问题,我会再进行更新的。我还要再说一下,我这里的处理方式并不一定能适用别人的场景,只是一个借鉴、思想。如果跟我的情况不行,估计要另想办法了,或自己开发或重写一些element-tree的源码,方法总比困难多不是吗?


于2021-06-22
最终我还是没能把这个方法走完,退化到了一个简单的方案,就是在拖拽后,重新刷新源节点的目标节点,这样因为数据库中数据还在,因此还是会出现的。那么怎么刷新父节点呢?

node.loaded = false;
node.epxand();

如果你发现node拿不到,那么真是一个遗憾的事情。在el-tree的node-drop事件处理函数中,参数分别是: draggingNode, dropNode, type, event,分别是拖拽的节点对象、拖放的节点对象、类型和事件对象。在这里draggingNode的parent属性我们拿不到。换一个思路,在node-drag-start事件时记录一下父节点,那个时候parent字段还不是空!

如果不小心帮助到了你,请帮忙点赞哦:)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于el-tree树展开节点后是另一个el-tree树的情况,你可以通过使用el-tree组件的自定义模板来实现。在展开节点时,你可以将子节点绑定到另一个el-tree组件的数据中。 首先,确保你已经在项目中引入了el-tree组件。然后,在你的Vue组件中,可以这样定义el-tree组件: ```html <template> <div> <el-tree :data="treeData" :node-key="nodeKey" :props="defaultProps" @node-click="handleNodeClick"></el-tree> </div> </template> <script> export default { data() { return { treeData: [ { label: '节点1', children: [ { label: '子节点1', children: [ { label: '子节点1.1', }, { label: '子节点1.2', }, ], }, ], }, { label: '节点2', children: [ { label: '子节点2', children: [ { label: '子节点2.1', }, { label: '子节点2.2', }, ], }, ], }, ], nodeKey: 'label', defaultProps: { children: 'children', label: 'label', }, }; }, methods: { handleNodeClick(data) { // 在这里处理节点点击事件 // 获取点击的节点数据data,然后将其作为新的数据赋值给另一个el-tree组件 this.treeData = data.children; }, }, }; </script> ``` 在上面的示例中,我们使用el-tree组件的data属性绑定了树的数据。当点击节点时,通过handleNodeClick方法获取到该节点的子节点数据,然后将其赋值给treeData,这样就实现了展开节点后显示另一个el-tree树的效果。 注意,你可以根据实际需求修改数据结构和事件处理逻辑。这只是一个简单的示例,希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值