有时候我问自己,为什么我干的前端的跟别人干的不一样,人家都是写写h5页面啥的就好了,为什么我非得那么苦逼的魔改各种组件,产品就不能按照现有的组件库设计产品吗?唉,说多了都是泪。不过这个也能让我有一定提升,只是这个提升是时间的极度浪费来达到的,毕竟在已有组件上就行修改还是很难的,总归是受限的。不说了,直接进入正题 吧。先看个截图,一图胜千言!!!
左边是一个棵完整的树,右边是选中的节点组成的树。我做过很多系统,一般都是用一棵树就搞定了,毕竟左边的树上已经有选中和取消选中的操作了。无奈产品经历非得说在树很大的时候,不太容易看清哪些节点被选中了。说的也有道理,不过我觉得更多的是要维护他的面子,只要开发提的建议一律不听就对了,按照自己的想法做!!无可奈何!!
说一下我的思路吧。
- 左右两棵树都用el-tree实现,我可不想自己徒手撸一棵树,我的脑细胞和头发都不允许我这么做
- 右边树使用el-tree的插槽来自定义节点的显示
- 右边树的数据根据树全量数据和选中节点生成(使用计算属性),选中节点从左边树的check事件中获取
- 删除右边树中的节点时,相应的更新左边树,并且把选中节点修正成删除节点后的结果,这样计算属性会重新计算,根本不用我自己从右边树中删除节点
下面就上面的几点给出代码,最后我会给出一个完成demo
右边树使用插槽
<el-tree
ref="rightTree"
:props="props"
:data="computedSelectedTreeData"
:expand-on-click-node="false"
node-key="id"
default-expand-all
@check="handleCheck">
<div class="custom-tree-node" style="width: 100%; position: relative" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span style="position: absolute; top: 2px; right: 5px" @click="() => handleRemoveItem(data, node)">
x
</span>
</div>
</el-tree>
右边树数据是计算属性
computedSelectedTreeData() {
if (this.selectedKeys && this.selectedKeys.length) {
return this.walkTreeData(this.treeData, this.selectedKeys)
}
return []
}
左边树check事件
handleCheck(data, param) {
this.selectedKeys = param.checkedKeys
}
右边树删除事件
handleRemoveItem(data, node) {
// 从selectedKeys中删除当前节点的祖先节点和孩子节点以及当前节点
const ids = []
function findId(nodes) {
nodes && nodes.forEach(node => {
ids.push(node.data.id)
node.childNodes && findId(node.childNodes)
})
}
findId(node.childNodes)
while(node) {
ids.push(node.data.id)
node = node.parent
}
const selectedKeys = this.selectedKeys
ids.forEach(id => {
const index = selectedKeys.indexOf(id)
index !== -1 && selectedKeys.splice(index, 1)
})
this.$refs.leftTree.setCheckedKeys(selectedKeys)
this.selectedKeys = selectedKeys
}
完成代码在这里,如果是404,说明还在审核中,请耐心等待
如果对你有帮助,请点赞哦:)