antd Tree树形控件——不完全选中子节点后想要获取父节点的值,与后端交互

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

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

如图:选中【新增用户】和【批量导入】时,想要把【用户列表】和【用户管理】的id也传给后端。
antd Tree树形控件——不完全选中子节点后想要获取父节点的值,与后端交互
通过阅读API文档
antd Tree树形控件——不完全选中子节点后想要获取父节点的值,与后端交互
onCheck是复选框选中时触发,其中第二个参数是一个事件对象,他的返回值打印出来如下:
antd Tree树形控件——不完全选中子节点后想要获取父节点的值,与后端交互
其中,有一个属性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说明:
antd Tree树形控件——不完全选中子节点后想要获取父节点的值,与后端交互
这样机会出现如果传入父节点 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}
               />
    }
}

成功!

上一篇:【乘法器】大数乘法器的设计与优化(32位,16位,8位 树型阵列乘法器Dadda Tree与Wallace Tree)


下一篇:数据结构、算法和应用 竞赛树-用相邻适配法求解箱子装载问题