上周的项目做到了一个需求是给角色分配菜单的时候,需要传给后台半选中状态的数据,可直接通过el-tree的方法设置获取的值是否包含半选中节点getCheckedNodes(false,true),我很想自己试着写一下,如果组件没有提供获取半选中节点的方法的话,我怎么来通过自己写的方法来通过选中节点拿到选中的所有节点(这里指的是选中状态和半选中状态的节点)。
//假设树结构是这样的
[
{
name:"A",
id:"A",
parentId:"-1",
children:[
{
name:"1",
id:"1",
parentId:"A",
children:[
{ name:"a",parentId:"1",id:"a" },
{ name:"b",parentId:"1",id:"b" }
]
},
{
name:"2",
id:"2",
parentId:"A",
children:[]
}
]
}
]
A
--1
----a
----b
--2
1.思路
最终效果:我通过拿到的id a,b,提交给后台希望保存的 A,1,a,b
- 1.目前后台返回给我parentId了,但我想在每一层对象上都记录到从根节点到目前节点的所有关系,这样我最后提交的时候只需要在当前对象上就可拿到所有节点了,然后set去重一下就ok了
- 2.我需要一个newparentId记录关系的话,那么我就需要递归这个树,并且我需要一个leave等级,来判断我在递归的时候是需要用parentId+当前id,还是用parent的newparentId+当前id
- 3.为了处理数据方便 我还是需要有一个对象数组来记录所有对象,这样遍历起来好操作,说通俗一点就是把一个树结构的数据给它踩平了,变成数组对象,可以直接用来遍历使用
2.实现
<template>
<div class="menuTree">
<el-dialog title="菜单权限" :visible.sync="menuVis" width="480px" :before-close="handleClose">
<el-button size="mini" type="primary" class="mt20" @click="saveFun">保存</el-button>
<el-tree
class="tree_div"
:style="{ height: scrollerHeight, overflow:'auto' }"
:data="treeData"
show-checkbox
node-key="id"
ref="tree"
highlight-current
:props="defaultProps">
</el-tree>
</el-dialog>
</div>
</template>
<script>
import { getMenuTree,addBaseResourceAuthority } from "@/api/baseapi";
export default {
props:['menuVis','openId'],
components: {},
computed: {
scrollerHeight: function(){
return (window.innerHeight - 500) + 'px';
}
},
data() {
return {
treeData:[],
defaultProps:{
children:"children",
label:"title"
},
allArray:[],
};
},
mounted() {
getMenuTree({ roleId: this.openId }).then(res=>{
if(res.status == 200){
this.treeData = res.data;
//设置等级
let nodeleave = 1;
this.treeToArray(this.treeData,nodeleave);
let selIdArray = [];
this.allArray.forEach(item=>{
if(item.checked){
selIdArray.push(item.id);
}
})
this.$refs.tree.setCheckedKeys(selIdArray);
}
})
},
methods: {
treeToArray(tree,nodeleave){
tree.forEach(item=>{ item.nodeleave = nodeleave; })
tree.forEach(item => {
//接受对象, 把所有对象都存起来
this.allArray.push(item);
if(item.nodeleave == 1){
//1级的时候拼接父对象和当前对象
item.newParentIds = item.parentId + ',' + item.id;
}else{
//下层的需要拼接父对象的newParentIds和当前对象
item.newParentIds = this.allArray.find(findobj=> findobj.id == item.parentId ).newParentIds + ',' + item.id;
}
if(item.children && item.children.length){
nodeleave = item.nodeleave + 1;
this.treeToArray(item.children,nodeleave);
}
});
},
handleClose(){
this.$emit('update:menuVis', false);
},
saveFun(){
let selchildrenId = this.$refs.tree.getCheckedKeys();
if(selchildrenId.length){
let querystring = "";
this.allArray.forEach(item=>{
selchildrenId.forEach(initem=>{
if(initem == item.id){
querystring = querystring + item.newParentIds + ",";
}
})
})
querystring = new Set(querystring.substring(0,querystring.length-1).split(','));
let query = {
authorityIds: Array.from(querystring).join(','),
roleId:this.openId
}
addBaseResourceAuthority(query).then(res=>{
if(res.status == 200){
this.$message.success('保存成功');
this.handleClose();
}
})
}else{
this.$message.warning('请勾选节点数据');
}
},
},
};
</script>
<style scoped lang="scss">
.menuTree{
::v-deep .el-dialog__body{
padding-top: 0;
}
.mt20{
margin: 10px 0 15px;
}
}
</style>