前言:
这个需求也是最近项目中遇到的,说实话是真的恶心。为啥这么说呢,是因为需求方根本就不知道真正的el-tree父子关联关系是什么样的,通知下来的要求就是要体现父子选中关系,那我自然就是直接使用的el-tree组件上默认的关系。结果提交后,需求方说我这不是树的父子关系,树的父子关系不是这样的,还质问我,选中父节点后,为什么下面的所有子节点都选中了。。。。我也是很无语。后来又详细沟通了下,才知道要的是下面这种效果
需求描述:
el-tree组件
1. 选中父节点,只勾选当前节点
2. 选中子节点,勾选上面所有的父节点,除了根节点
3. 取消勾选子节点,如果有同级子节点是勾选状态,父节点不取消勾选;反之取消
效果展示:
修改el-tree组件的父子关系,选中节点后向上选中所有父级
代码实现:
html部分:
<template>
<div>
<el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input>
<el-tree
ref="tree"
:data="data"
node-key="label"
default-expand-all
show-checkbox
:props="defaultProps"
:check-strictly="true"
:filter-node-method="filterNode"
@check="handleCheck"
>
</el-tree>
</div>
</template>
JavaScript部分:
<script>
export default {
data() {
return {
// 树数据
data: [
{
id: 1,
label: '根目录',
parentId: -1,
creater: '小明',
disabled: true,
children: [
{
id: 2,
label: '一级 1',
parentId: 1,
creater: '小朋',
children: [
{
id: 5,
label: '二级 1-1',
parentId: 2,
creater: '王五',
children: [
{
id: 9,
label: '三级 1-1-1',
parentId: 5,
creater: '张三',
},
{
id: 10,
label: '三级 1-1-2',
parentId: 5,
creater: '张三',
},
],
},
],
},
{
id: 3,
label: '一级 2',
parentId: 1,
creater: '小明',
children: [
{
id: 6,
label: '二级 2-1',
parentId: 3,
creater: '小明',
},
{
id: 7,
label: '二级 2-2',
parentId: 3,
creater: '小鹏',
},
],
},
{
id: 4,
label: '一级 3',
parentId: 1,
creater: '小鹏',
children: [
{
id: 8,
label: '二级 3-1',
parentId: 4,
creater: '小丽',
},
{
id: 11,
label: '二级 3-2',
creater: '小丽',
children: [
{
id: 12,
label: '三级 3-2-1',
parentId: 11,
creater: '张三',
},
{
id: 13,
label: '三级 3-2-2',
parentId: 11,
creater: '王五',
},
{
id: 14,
label: '三级 3-2-3',
parentId: 11,
creater: '小丽',
},
],
},
],
},
],
},
],
defaultProps: {
children: 'children',
label: 'label',
},
// 默认选中节点
defaultCheckedKeys: [],
}
},
methods: {
/**标签树的复选框点击事件 */
handleCheck(node) {
this.upTreeParent(node)
},
/**树结构向上查找父标签节点 */
upTreeParent(node) {
// 获取点击标签节点的父标签节点
const parentNode = this.$refs.tree.getNode(node).parent.data
// 获取点击标签节点的兄弟节点
const sublings_list = parentNode.children
// 获取当前选中的标签节点,用来获取当前的选中状态
const nodeChecked = this.$refs.tree.getCheckedNodes()
const isNodeChecked = nodeChecked.some((i) => i.id == node.id)
if (isNodeChecked) {
// 添加点击的标签
this.defaultCheckedKeys.push(node.label)
} else {
// 移除点击的标签
this.defaultCheckedKeys = this.defaultCheckedKeys.filter(i => i !== node.label)
}
if (parentNode) {
if (isNodeChecked) {
if (parentNode.id !== 1) {
this.defaultCheckedKeys.push(parentNode.label)
}
} else {
// 此处需要判断,如果取消勾选,是否有同级别的兄弟标签有勾选的状态,如果有,则父标签不取消勾选
const subling_listArr = sublings_list.map((item) => item.label)
// 有则flag为true
let flag = this.defaultCheckedKeys.some(i =>subling_listArr.includes(i))
// 如果同级节点没有勾选,则取消父节点的勾选
console.log(flag, 'flag')
if (!flag) this.defaultCheckedKeys = this.defaultCheckedKeys.filter((i) => i !== parentNode.label)
}
// 去重
this.defaultCheckedKeys = Array.from(new Set(this.defaultCheckedKeys))
console.log('defaultCheckedKeys', this.defaultCheckedKeys)
// 设置勾选上的节点
this.$refs.tree.setCheckedKeys(this.defaultCheckedKeys)
// 递归向上查找所有父节点
if (parentNode.parentId !== -1) {
this.upTreeParent(parentNode)
}
}
},
},
}
</script>