最近有一个权限树的需求,而且树的结构比较深,想要实现,在不完全选中子节点后能够获取父节点的值,一并传给后端。

不完全选中子节点后想要获取父节点的值

如图:选中【新增用户】和【批量导入】时,想要把【用户列表】和【用户管理】的id也传给后端。
在这里插入图片描述
通过阅读API文档
在这里插入图片描述
onCheck是复选框选中时触发,其中第二个参数是一个事件对象,他的返回值打印出来如下:
在这里插入图片描述
其中,有一个属性halfCheckedKeys就是关联父节点的值。这样,我们可以轻松的拿到值了,和选中节点拼接起来一起传给后台就好了。

onCheck = (checkedKeysValue, e) => {
    console.log('onCheck', checkedKeysValue);
    console.log('e.halfCheckedKeys :>> ', e);
    const checkedKeysResult = [...checkedKeysValue, ...e.halfCheckedKeys]
    this.setState({
        allCheckedId: checkedKeysResult
    })
};

解决反写的时候,如果传入父节点 key,则子节点自动选中的问题

上面的处理在新建的时候没有问题,一旦到了编辑或者查看的时候,需要反写权限树,就会出问题,因为我们是受控组件,用到了checkedKeys,选中复选框的树节点。请看API说明:
在这里插入图片描述
这样机会出现如果传入父节点 key,则子节点自动选中的情况。现在处理这个问题。

  • 首先,在渲染树结构时把所有的叶子节点存在一个数组,叫childArr
  • 接着,利用后端接口返回的id数组(有父节点,有叶子节点)与childArr数组比较,取出相同的元素(可考虑使用lodash的_.intersection方法
  • 最后,将获得的新数组给Tree组件的checkedKeys赋值

完整的权限树结构代码:

import React from 'react';
import { Tree } from 'antd';
let _ = require('lodash');

let childArr = []   // 存放所有子节点的数组

export default class CmpAuthTree extends React.Component {
    constructor(props) {
        super(props);
        this.getData(this.props.treeData)
        this.state = {
            autoExpandParent: true,
            expandedKeys: this.props.checkedList || [],
            allCheckedId: []   // 传给后台的id数组
        }
    }

    componentDidMount() {
        this.initData()
    }

    componentDidUpdate(prevProps) {
        this.updateData(prevProps)
    }

    initData = () => {
        let uniqueChild = this.dataClean(this.props.checkedList)
        this.setState({
            checkedKeys: uniqueChild || []
        })
    }

    updateData = (prevProps) => {
        let uniqueChild = this.dataClean(this.props.checkedList)
        if (prevProps.checkedList?.length !== this.props.checkedList?.length) {
            this.setState({
                expandedKeys: this.props.checkedList || [],
                checkedKeys: uniqueChild || []
            })
        }
    }

    getData = (data) => {
        data.map(res => {
            res.title = res.name
            res.key = res.menuId
            if (res.children && res.children.length > 0) {
                this.getData(res.children)
            } else {
                childArr.push(res.menuId)
            }
        })
        return childArr
    }

    dataClean = (checkedList) => {
        let allChildArr = this.getData(this.props.treeData)
        let uniqueChild = _.intersection(checkedList, allChildArr)
        return uniqueChild
    }

    onExpand = (expandedKeysValue) => {
        console.log('onExpand', expandedKeysValue);
        this.setState({
            autoExpandParent: false,
            expandedKeys: expandedKeysValue
        })
    };

    onCheck = (checkedKeysValue, e) => {
        console.log('onCheck', checkedKeysValue);
        console.log('e.halfCheckedKeys :>> ', e);
        const checkedKeysResult = [...checkedKeysValue, ...e.halfCheckedKeys]
        let uniqueChild = this.dataClean(checkedKeysResult)
        this.setState({
            allCheckedId: checkedKeysResult,
            checkedKeys: uniqueChild
        })
    };

    getCheckedList() {
        return this.state.allCheckedId
    }

    render() {
        return <Tree
            // defaultExpandAll
            disabled={this.props.readOnly}
            checkable
            selectable={false}
            onExpand={this.onExpand}
            expandedKeys={this.state.expandedKeys}
            autoExpandParent={this.state.autoExpandParent}
            onCheck={this.onCheck}
            checkedKeys={this.state.checkedKeys}
            treeData={this.props.treeData}
               />
    }
}

成功!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐