配置 :check-strictly=true
取消el-tree自带的联动
- 原因:
1、比如我只需要配置父菜单,联动的话会导致下面的子菜单和按钮一起勾上;
2、回显数据时,如果后端返回了一个父节点id,但是前端会把它下面的子节点也全都勾上;
取消联动后的问题
1、只能一个个的勾选,如果权限数量过多就很麻烦;
2、可能存在只勾选了按钮,菜单没勾选的情况;
解决方案
1、在右边另外加了个全选的按钮;
2、自定义联动方案:
-- 选中时,关联所有父节点
-- 取消选中时,关联所有子节点
说明: 其实在ztree官网demo中是可以直接配置这种联动方式的,但是elementUI中没找到,所以就自己监听复选框点击事件来实现吧
代码:
就一个html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-tree
:data="data2"
show-checkbox
node-key="id"
ref="tree"
default-expand-all
:props="defaultProps"
v-model="defaultCheckedMenuId"
:default-checked-keys="defaultCheckedMenuId"
:check-strictly=true
:expand-on-click-node=true
:check-on-click-node=false
@check="handleNodeClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{
{ node.label }}</span>
<span :hidden="!data.children">
<el-button
type="text"
size="mini"
@click.stop="() => checkAllChild(node, data)">
全选子节点
</el-button>
</span>
</el-tree>
<button @click=showcheckedids()>打印已选择ids</button>
</div>
</body>
<!-- 先引入 Vue -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
var vm = new Vue({
el: '#app',
// template: `
// <el-tree
// :data="data2"
// show-checkbox
// node-key="id"
// ref="tree"
// default-expand-all
// :props="defaultProps"
// v-model="defaultCheckedMenuId"
// :default-checked-keys="defaultCheckedMenuId"
// :check-strictly=true
// :expand-on-click-node=true
// :check-on-click-node=false
// @check="handleNodeClick"
// >
// <span class="custom-tree-node" slot-scope="{ node, data }">
// <span>{
{ node.label }}</span>
// <span :hidden="!data.children">
// <el-button
// type="text"
// size="mini"
// @click.stop="() => checkAllChild(node, data)">
// 全选子节点
// </el-button>
// </span>
// </el-tree>`,
data: {
data2: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 91,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2',
children: [{
id: 9,
label: '四级 1-1-2-1'
}]
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
},
{
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}],
defaultProps: {
id: "id",
children: 'children',
label: 'label'
},
defaultCheckedMenuId: [91],
checkedKeys: [-1]
},
methods: {
handleNodeClick(data) {
var node = this.$refs.tree.getNode(data.id);
var isChecked = node.checked;
// console.log(data, isChecked);
// console.log(node);
// console.log(node.data.id);
var ids = [];
if(node.checked){
// 选中时,关联所有父节点
this.recusionFindParentIds(node, ids);
}else{
// 取消选中时,关联所有子节点
this.recusionFindChildIds(node, ids);
}
this.setCheckedByIds(ids, isChecked);
// console.log(ids);
},
// 根据ids设置节点的选中状态
setCheckedByIds: function(ids, isChecked){
// console.log(ids, isChecked);
if(ids){
for(var i=0; i<ids.length; i++){
this.$refs.tree.setChecked(ids[i], isChecked);
}
}
},
// 打印已选择的节点 ids
showcheckedids: function () {
console.log("getCheckedKeys\t " + this.$refs.tree.getCheckedKeys());
checkedKeys = this.$refs.tree.getCheckedKeys();
},
// 联动所有子节点
checkAllChild: function(node, data) {
// console.log(node, data);
// 点击后的状态: 与点击前相反
var isChecked = !node.checked;
var childIds = [];
this.recusionFindChildIds(node, childIds);
this.setCheckedByIds(childIds, isChecked);
// 如果是要设置为选中,则还需要联动父节点
if (isChecked){
var parentIds = [];
this.recusionFindParentIds(node, parentIds);
this.setCheckedByIds(parentIds, true);
}
},
// 递归获取所有子节点id
recusionFindChildIds: function(node, childs){
var data = node.data;
childs.push(data.id);
var nodes = node.childNodes;
if(!nodes) return;
for(var i=0; i<nodes.length; i++ ){
var curNode = nodes[i];
childs.push(curNode.data.id);
if(curNode.childNodes){
var list = curNode.childNodes;
for(var j=0; j<list.length; j++){
this.recusionFindChildIds(list[j], childs);
}
}
}
},
// 递归获取所有父节点id
recusionFindParentIds: function(node, parentIds){
var data = node.data;
if(data.id==0) return;
parentIds.push(data.id);
if(node.parent){
this.recusionFindParentIds(node.parent, parentIds);
}
},
}
})
</script>
</html>