1.背景
最近在做基于React-admin
项目的权限管理系统,所有的权限都是基于api
的,即通过为角色下发的具体api
来获取用户是否有对某路由可见(根据后端返回的路由表,动态生成前端菜单)以及路由下模块的操作权限(即增删改查)。
在为角色分配具体的权限的时候,是通过Tree
组件来进行配置的,管理员勾选用户具有某个模块下(这里的模块指的就是前端路由)的具体的某些功能,设计思路就是,只要是选择了增删改查的任一节点,则用户具有访问该路由的权限,增删改查一个都不选择的时候,用户就没有查看该路由的权限,即该路由(菜单)对用户不可看。
功能实现后,发现如果这样去分配用户权限,可以控制到最小的单元(即操作单元)。问题是,如果给用户分配了添加功能,而没有分配查看list
功能,那么用户添加后也无从查看。所以无论是增删改操作后,用户都无法从list
去查看操作效果,所以这里就需要改一下逻辑,当用户选择其他非list节点时,默认勾选list节点
。
这就牵扯到如何在tree
中进行联动的问题了?
2.处理Tree
节点联动
在上面提到了,需要在勾选增删改
节点时,需要联动勾选list
节点 .
前提是你的每个节点都应该有这两个属性
- key:当前tree node节点的唯一值,这里根据模块来进行命名的,而且绑定key到tree node上,在实际下发的时候也是只会下发key值。
- parent:当前节点的父节点,这个可以用于根据父节点去构建一个动态树
问题都清楚了,下面就是如何实现 。
查看了一下antd tree
组件的使用方法找到了思路
这是官方给出的方法,当选中或者取消勾选时都会触发这个方式,其中有个checked
属性,我们看一下打印结果
其中checkedNodes
中表示已经选中的节点,这里是叶子节点。我们可以通过对叶子节点的处理来实现我们的联动问题。
具体思路:
- 遍历
checkedNodes
获取每个节点item
的parent
属性,该属性指向上级节点的key
- 判断当前的节点是不是
list
的节点,即使用parent key
拼接_list
来判断当前遍历的item.key
是否与parentkey_list
相等。- 如果相等,说明当前选中的节点中包含了
list
的节点,那么就不需要向checkedKeys
中添加该节点的key
- 如果不相等,则去
checkedKey
中判断list
节点是否存在- 如果存在,则不添加到
checkedKey
中,否则添加- 如果选中任一非
list
节点,那么应该联动勾选list
节点,且不可取消勾选list
节点- 如果想取消
list
节点,则必须要取消其他同级勾选的节点
思路有了,那么就是如何撸代码了,测试可用的代码就在下面了,就不赘述了
// 导入lodash
import _ from 'lodash'
// 选中的节点,如果选中某节点下的叶子节点则默认选中列表list节点
onCheck = (checkedKeys, checked) => {
const nodes = checked.checkedNodes
_.map(nodes,node=>{
const parent = node.parent
const key = parent+'_list'
/**
* 1.判断当前选中的节点是不是list节点
* 2.如果是,则不添加
* 3.如果不是则判断checkedKeys中是否存在list节点
* 4.如果不存在则添加,如果存在则不添加
* 5.如果选中任一个不是list节点,则选中list节点,且不可取消勾选list节点
* 6.如果想取消list节点,则必须取消其他的节点勾选状态
*/
if(key !== node.key){
if(_.findIndex(checkedKeys, function(o) { return o === key; }) < 0){
checkedKeys.push(key)
}
}
})
console.log("checkedKeys",checkedKeys)
this.setState({ checkedKeys, authority: checkedKeys })
};