react tree数选择如何实现多组联动

react+antdesign使用tree数选择组件,如何实现多组联动?
想要实现的是:一个员工可能存在多个分组,比如我在分组一中勾选张三,分组二、分组三中的张三也要同步勾选上,目前后端返回数据人员id相同,这样的话就导致树结构数据混乱出现脏数据,如果设置不同的key值又会出现点击第一个分组张三不生效,但是最后一个张三会被勾中

img

源于ChatGPT仅供参考


要实现多组联动,可以考虑使用 React 的状态管理来实现。首先需要在组件的 `state` 中定义一个用于存储选中节点的数组,然后在 TreeSelect 组件中通过 `value` 属性和 `onChange` 事件进行绑定。每次勾选或取消勾选一个节点时,都更新选中节点的数组,并根据当前选中的节点自动选中其它相关节点。

下面是一个简单的示例代码:

```jsx
import React, { useState } from 'react';
import { TreeSelect } from 'antd';

const treeData = [
  {
    title: '分组一',
    value: 'group1',
    children: [
      {
        title: '员工A',
        value: 'employeeA',
      },
      {
        title: '员工B',
        value: 'employeeB',
      },
    ],
  },
  {
    title: '分组二',
    value: 'group2',
    children: [
      {
        title: '员工A',
        value: 'employeeA',
      },
      {
        title: '员工C',
        value: 'employeeC',
      },
    ],
  },
];

function App() {
  const [selectedKeys, setSelectedKeys] = useState([]);

  function handleChange(value) {
    setSelectedKeys(value);
  }

  function getRelatedKeys(key) {
    const relatedKeys = [];
    treeData.forEach(node => {
      if (node.children && node.children.some(child => child.value === key)) {
        relatedKeys.push(node.value);
      }
    });
    return relatedKeys;
  }

  function handleCheck(checkedKeys, info) {
    // 获取当前操作的节点
    const currKey = info.node.props.value;

    // 获取和当前节点相关的所有节点
    const relatedKeys = getRelatedKeys(currKey);

    // 生成最终选中的节点数组
    const finalSelectedKeys = selectedKeys.filter(key => !relatedKeys.includes(key)).concat(checkedKeys);

    // 更新选中节点数组状态
    setSelectedKeys(finalSelectedKeys);
  }

  return (
    <TreeSelect
      treeData={treeData}
      value={selectedKeys}
      onChange={handleChange}
      treeCheckable
      showCheckedStrategy="SHOW_PARENT"
      onCheck={handleCheck}
    />
  );
}

export default App;

上述代码中,通过 useStatesetSelectedKeys 定义了选中节点的数组 selectedKeys,然后通过 value 属性和 onChange 事件将 TreeSelect 组件和 selectedKeys 绑定起来。在 handleCheck 函数中,先获取当前操作的节点和其它相关节点,然后根据当前选中的节点自动选中其它相关节点,并更新选中节点的数组状态。最终将 selectedKeys 数组作为 TreeSelect 组件的 value 属性值传入,就可以渲染出一个多组联动的 TreeSelect 组件了。


  • 这篇博客: React Ant Design Tree树形控件 点击控制全部展开和全部收起中的 React Ant Design Tree树形控件 点击控制全部展开和全部收起 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 在这里插入图片描述

    import { message, Tree } from 'antd';
    import IconFont from '@/components/IconFont';
    import React, { Fragment, PureComponent } from 'react';
    import styles from './SelectTree.less';
    import TreeOperate from "@/components/case/TreeOperate";
    import { connect } from 'dva';
    import { getQueryVariable } from '@/utils/fun'
    
    const TreeNode = Tree.TreeNode;
    
    @connect((state) => {
      return { ...state.testcase };
    })
    
    class SelectTree extends PureComponent {
      state = {
        autoExpandParent: true,
        projectsId:getQueryVariable('projectsId'),
      };
    
      componentDidMount() {
        this.init()
        this.props.onRef(this)
      }
    
      init = () => {
        const projectsId = getQueryVariable('projectsId');
        this.props.dispatch({
          type: 'testcase/fetchCaseTree',
          payload: { projectsId, menuType: 1, name: '' }
        })
      }
    
      onCheck = (keys) => {
        this.props.dispatch({
          type: 'testcase/onCheck',
          payload: { keys: keys.checked ? keys.checked : keys }
        })
      }
    
      subKeys = (data, key, result) => {
        data.forEach(v => {
          if (v.children) {
            this.subKeys(v.children, result);
          }
        })
        return result;
      }
    
      //展开具体某个的方法
      onExpand = expandedKeys => {
        this.setState({
          expandedKeys,
          autoExpandParent: false,
        });
      };
    
      deepTraversa = (node, nodeList = []) => {
        if (node !== null) {
          nodeList.push(node.key + '')
          let children = node.children
          for (let i = 0; i < children.length; i++) {
            this.deepTraversa(children[i], nodeList)
          }
        }
        return nodeList
      }
    
    //展开全部
      onExpandAll = () => {
        const { caseDate } = this.props;
        const expandedKeys = [];
        caseDate.forEach(item => {
          expandedKeys.push(this.deepTraversa(item))
        })
        this.setState({
          expandedKeys: expandedKeys.flat()
        });
      }
    
    //收起全部
      onExpandClose = () => {
        this.setState({
          expandedKeys: []
        });
      }
    
      onDrop = ({ event, node, dragNode, dragNodesKeys}) =>{
        console.log('拖拽')
      }
    
      render() {
        const { caseDate, checkedKeys } = this.props;
        const { expandedKeys, autoExpandParent } = this.state;
    
        const IconFolder = ({ k }) => <IconFont type="icon-wenjianjia3" className={styles.icon_title} onClick={() => {
          const subKeys = this.subKeys(caseDate, k, []);
          this.onCheck({ checked: [...checkedKeys.checked.filter(v => subKeys.indexOf(v) === -1), ...subKeys.filter(v => checkedKeys.checked.indexOf(v) === -1)] })
        }} />
    
        const getData = (data, key = null) => {
          const newData = data || []
          return newData.map((item, index) => {
            if (item.children && item.node_type === "menu") {
              return (
                <TreeNode title={<TreeOperate title={item.title} sourceData={item} ></TreeOperate>} selectable={false}
                  key={item.key}
                  icon={<IconFolder k={item.key} />} checkable={false}>
                  {getData(item.children, item.key)}
                </TreeNode>
              )
            }
          })
        }
    
        return (
          <div style={{ overflowY: 'auto', height: '500px' }}>
            <Tree checkable showLine showIcon blockNode draggable
              className="hide-file-icon" checkStrictly
              checkedKeys={checkedKeys.checked}
              onCheck={this.onCheck}
              onDrop={this.onDrop}
              expandedKeys={expandedKeys}
              onExpand={this.onExpand}
              autoExpandParent={autoExpandParent}>
              {getData(caseDate)}
            </Tree>
          </div>
        )
      }
    }
    
    export default SelectTree;