elementUI中el-tree的处理数据时半选框父级选中问题(让数据中子级不全选中时,父级不选中即半选)
1.业务需求:
- 在后台权限管理系统中,在菜单管理模块中分配当前角色的菜单权限时,菜单权限的初始状态获取时,后端返回数据结构一般是一个菜单的树形结构与一个菜单选中的list列表。然后前端需要将两者进行匹配,然后追加到el-tree树形中。其中子级全选时,父级也会选中,但是由于el-tree的设计原理,当子级未全选中时,父级是不会选中的(此时为半选),因此,此时在传给后端的list中是没有父级的,由于后端的需要,此时是需要将半选的父级也传给后端,注意,在获取初始菜单树状态的list中,半选状态的父级也返回回来了,此时如果直接渲染的话,由于el-tree的设计原理,如果有父级那么就选中所有子级,此时,未全选中的子级就会被全选,这就是问题所在。
2.需求分析:
- 个人觉得el-tree这种设计原理不太友好,因为做递归去处理这种属性结构的数据是很难受的~~~,一般情况下是只要有子级选中那么父级就选中,子级全不选中则父就不选中。而el-tree设计是只有子级全选中时父级才选中,子级未全选时父级为半选(此时其实为未选中),当子级全不选时父级为不选中。
3.解决方案:
- 好了,直奔主题!首先在菜单权限树形选择时,半选状态的父级的ID是需要加入list中的,那么此时将
halfCheckedKeys
加入list即可:
// 节点选中状态变化
changeNowNode(data, obj) {
// 获取选中的key
this.$nextTick(() => {
this.setCheckedList = this.$refs.dutytree.getCheckedKeys()
if (obj.halfCheckedKeys.length>0) {
obj.halfCheckedKeys.forEach(item=> {
this.setCheckedList.push(item)
})
}
})
},
- 将上面选中的list传给后台时,然后在获取菜单权限初始状态时,我们会得到一个菜单树形结构数据与一个选中的菜单ID列表,然后根据递归进行匹配。注意,此时的一个问题是,如果是半选状态的父级,它的ID也会在list中,此时我们匹配完去渲染是就会存在只要有父级,那么它下面的所有子级都会选中的问题,此时我们要的效果是父级半选,子级不全选,所以在递归函数中进行如下改造:
findFunc(permissionsList, LimitData) {
let that = this
let isExit = false
for (let j = 0; j < LimitData.length; j++) {
if (LimitData[j].children.length>0) {
// 如果有children,那么说明它是父级
isExit = false
that.findFunc(permissionsList, LimitData[j].children)
} else {
// 当它是子级时再进行匹配
for (let i = 0; i < permissionsList.length; i++) {
if (LimitData[j].sysResourcesId == permissionsList[i]) {
// 菜单权限匹配
that.setChecked.push(LimitData[j].sysResourcesId)
} else {
// 且没有匹配成功
isExit = true
}
}
}
}
if (isExit) { // 循环完成后进行判断
return false
}
},