天天看點

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}
               />
    }
}

           

成功!

繼續閱讀