需求:
1、菜单树多选
2、父子节点不关联,互不影响
3、最多可勾选3条,大于3其余复选框禁选
4、将勾选的节点,按父子层级拼接name回显页面(如勾选了二级,需将一级name拿到并拼接起来:一级/二级)
5、回显页面的name可删除,删除的同时需同步更新菜单树勾选状态,禁选状态
效果图:
代码:
<template>
<div>
<center>
<h3>多选+禁选</h3>
<div class="treeContent">
<div v-if="checkList.length">
<p v-for="item in checkList" :key="item.id">
{{item.menuName}}
<span class="remove" @click="onRemove(item.id)">X</span>
</p>
</div>
</div>
<el-tree
:data="treeList"
ref="tree"
show-checkbox
check-strictly
node-key="id"
:props="defaultProps"
@check="onTreeCheck"
></el-tree>
<el-button type="primary" @click="clickss">确定</el-button>
</center>
</div>
</template>
<script>
export default {
data() {
return {
checkList: [], //勾选的数据
list: [
{
id: 1,
label: "一级 1",
children: [
{
id: 4,
label: "二级 1-1",
fatherID: 1,
children: [
{
id: 9,
label: "三级 1-1-1",
fatherID: 4
},
{
id: 10,
label: "三级 1-1-2",
fatherID: 4
}
]
}
]
},
{
id: 2,
label: "一级 2",
children: [
{
id: 5,
label: "二级 2-1",
fatherID: 2,
children: [
{
id: 14,
label: "三级 2-1-1",
fatherID: 5
},
{
id: 15,
label: "三级 2-1-2",
fatherID: 5
}
]
},
{
id: 6,
label: "二级 2-2",
fatherID: 2
}
]
},
{
id: 3,
label: "一级 3",
children: [
{
id: 7,
label: "二级 3-1",
fatherID: 3
},
{
id: 8,
label: "二级 3-2",
fatherID: 3
}
]
},
{
id: 11,
label: "一级 4",
children: []
}
],
defaultProps: {
children: "children",
label: "label"
},
treeList: [],
checkListCopy: [],
checkArr: []
};
},
mounted() {
this.treeList = this.list;
},
methods: {
onTreeCheck(data, treeInfo) {
let thisNode = this.$refs.tree.getNode(data.id),
keys = [data]; // 获取已勾选节点的key值
console.log("thisNode----------------", thisNode);
if (thisNode.checked) {
// 当前节点若被选中
for (let i = thisNode.level; i > 1; i--) {
// 节点之上有父节点,继续往上查,将选中节点相关联的父节点都存入keys数组
thisNode = thisNode.parent;
keys.unshift(thisNode.data);
}
//将选中的数据的id,以及拼接好的name存起来
this.checkListCopy.push({
id: data.id,
menuName: keys.map(i => i.label).join("/")
});
} else {
this.checkListCopy.forEach((item, index) => {
if (item.id == data.id) {
this.checkListCopy.splice(index, 1);
}
});
}
const checkedKeys = treeInfo.checkedKeys || [];
//最多勾选3条,大于3其余复选框禁选
this.updateTreeStatus(checkedKeys, checkedKeys.length >= 3);
},
//确定
clickss() {
this.checkList = JSON.parse(JSON.stringify(this.checkListCopy));
},
//删除
onRemove(id) {
this.checkList.forEach((i, k) => {
if (i.id == id) {
this.checkList.splice(k, 1);
}
});
this.checkListCopy.forEach((i, k) => {
if (i.id == id) {
this.checkListCopy.splice(k, 1);
}
});
const keyList = this.checkList.map(i => i.id);
this.$refs.tree.setCheckedKeys(keyList, true); //更新复选框状态
this.updateTreeStatus(keyList, keyList.length >= 3); //禁选处理
},
// 禁选处理
updateTreeStatus(checkedKeys, status = false) {
const treeRef = this.$refs.tree;
if (treeRef) {
const treeStore = treeRef.store || {};
const treeNodesMap = treeStore.nodesMap || {}; //tree node集合
Object.keys(treeNodesMap).forEach(key => {
const item = treeNodesMap[key] || {};
if (!checkedKeys.includes(Number(key))) {
//更新未勾选的复选框的禁选状态
let data = item.data || {};
data.disabled = status;
treeRef.setCurrentNode(data);
}
});
}
}
}
};
</script>
<style scoped>
.treeContent {
width: 300px;
min-height: 30px;
border: 1px solid black;
display: flex;
flex-direction: column;
margin: 20px auto;
padding: 0 10px;
}
p {
display: flex;
justify-content: space-between;
}
.remove {
font-size: 14px;
color: brown;
}
</style>