关于ElementUI的tree组件的一个复杂需求:
需求:从模板树生成实例树,要求实例树的节点可复制多个,具体如图
刚拿到这个需求的时候我的脑子是懵逼的,因为刚做了一个选择tree中被选中的节点(如果子节点全部被选中的话只保留父节点信息)的需求,最后通过仿照源码自己写了逻辑处理实现了,内心正在膨胀中,第一反应,通过store,根据已有的方法只能得到包含选中的节点的n棵树,然后要将所有的树进行合并,这是这一步在当时并不会做,因为自己还满脑子store,store的,怎么操作store来做。我将需求分解成了4步:
1.通过左边的选中生成最基本的实例树
2.点击右侧实例树相应节点可复制节点
3.点击模板树中实例树没有的节点,可在实例树中生成对应节点
4.将实例树的数据传递给后台进行保存
首先还没开始就卡住了:怎么复制树!刚开始一直陷入了store的魔咒中,想通过复制this.$refs.treeLeft.store来生成右侧的树,行不通!!!(不过在此过程中让我深刻认识到了vue中的数组,对象的深拷贝)
第二天突然想到为什么不直接用组件生成一个树不就好了,两者都公用一组数据(深拷贝!!!不能浅拷贝,否则两个树分不开了),好了终于解决第一个问题了
代码如下:
<div class="treeLeft">
<el-tree
:data="treeData_left"
show-checkbox
node-key="id"
@check="leftTreeChecking"
ref="treeLeft"
:expand-on-click-node="flag_treeNodeClickOpen"
:props="defaultProps">
</el-tree>
</div>
<div class="buttonWrap">
<el-button type="primary" size="mini" @click="cerateCollectionItemInstance">
<i class="el-icon-arrow-left el-icon--left"></i>
生成
<i class="el-icon-arrow-right el-icon--right" ></i>
</el-button>
</div>
<div class="treeRight">
<el-tree
:data="treeData_right"
show-checkbox
node-key="id"
@node-click="rightTreeChecking"
@node-contextmenu="rightTreeRightClick"
ref="treeRight"
:default-checked-keys="defaultCheckedRight"
:expand-on-click-node="flag_treeNodeClickOpen"
:props="defaultProps">
</el-tree>
</div>
请求后台然后通过深拷贝将数据赋值给两个树即可
开始第一步:将左侧选中的在右侧树中体现出来(即将没有选中的删除)
这一步还是比较简单的,不过暂时需要借助按钮来实现,当点击按钮的时候,得到左侧选中的key数组,赋值给右侧,右侧树进行遍历,将没选中的删除即可,难点在于遍历删除:
自己写了个方法:
getCheckedNodesByZM(storeLeft,storeRight){
// 根据左树选中节点过滤右树
storeRight.setCheckedKeys(storeLeft.getCheckedKeys())
// 传过来一个完成的树,不在原数据上操作
// 将左侧的选中节点赋值给右侧的默认选中
// this.$set(this,'defaultCheckedRight',this.copyDeep(storeLeft.getCheckedKeys()))
const removeUselessData = function(node){
const childNodes = node.root ? node.root.childNodes : node.childNodes;
let len = childNodes.length
for (let j = 0; j < len; j++) {
if(childNodes[j].isLeaf){
if(!childNodes[j].checked){
// 没被选中的叶子节点
storeRight.remove(childNodes[j]);
j--
len = len - 1
}
else{
// 被选中的叶子节点
}
}else {
if(childNodes[j].indeterminate || childNodes[j].checked){
removeUselessData(childNodes[j]);
}else{
storeRight.remove(childNodes[j]);
j--
len = len - 1
}
}
}
};
removeUselessData(storeRight);
return storeRight;
},
这个方法后面也会用到,可以将参数改为一个,在一个树上面进行过滤
这样第一步算是完成了
接下来第二步&