【React3 树形控件的实现】支持多展开父节点和单选子节点功能

文章介绍了在React3版本中使用AntDesign的Tree组件遇到的问题及解决方法,包括如何处理树形数据结构,设置多选树状结构,以及初始化state。还提到了onSelect函数的逻辑处理,确保父节点和子节点的交互符合需求。
摘要由CSDN通过智能技术生成

React树形控件

最近学习了前端的知识,搭建页面过程中,使用树状组件遇到了很大问题,总结一下。(使用的是react3版本,在vscode中进行编写)

1. 首先提供树状组件的数据为树形,树的结构不是这种的,可以利用循环将其修改为次类型。具体结构如下(treeData应该放在this.state中)

treeData  =  [
  {
    title: '0-0',
    key: '0-0',
    children: [
      {
        title: '0-0-0',
        key: '0-0-0',
        children: [
          { title: '0-0-0-0', key: '0-0-0-0' },
          { title: '0-0-0-1', key: '0-0-0-1' },
          { title: '0-0-0-2', key: '0-0-0-2' },
        ],
      },
      {
        title: '0-0-1',
        key: '0-0-1',
        children: [
          { title: '0-0-1-0', key: '0-0-1-0' },
          { title: '0-0-1-1', key: '0-0-1-1' },
          { title: '0-0-1-2', key: '0-0-1-2' },
        ],
      },
      {
        title: '0-0-2',
        key: '0-0-2',
      },
    ],
  },
  {
    title: '0-1',
    key: '0-1',
    children: [
      { title: '0-1-0-0', key: '0-1-0-0' },
      { title: '0-1-0-1', key: '0-1-0-1' },
      { title: '0-1-0-2', key: '0-1-0-2' },
    ],
  },
  {
    title: '0-2',
    key: '0-2',
  },
];

2. 根据ant design 中的树状结构选择可用的树。以可多选的树形结构为例子:

<Tree
       checkable //是否可以在节点前添加 Checkbox 复选框,未使用可以不写
       onExpand={this.onExpand.bind(this)}//展开/收起节点时触发,一般情况下不需要对onExpand函数进行修改
       expandedKeys={this.state.expandedKeys} //(受控)展开指定的树节点, expandedKeys必须是一个array类型的数据
       autoExpandParent={this.state.autoExpandParent}//是否自动展开父节点
       onCheck={this.onCheck.bind(this)} //点击复选框触发,一般情况下不需要对onCheck函数进行修改
       checkedKeys={this.state.checkedKeys}//(受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点 key,则子节点自动选中;相应当子节点 key 都传入,父节点也自动选中。当设置checkable和checkStrictly,它是一个有checked和halfChecked属性的对象,并且父子节点的选中与否不再关联. checkedKeys也需要是array类型的数据
       onSelect={this.onSelect.bind(this)} //点击树节点触发,使用时想要点击父节点时展开树,并且不进行页面刷新,因此需要对onSelect函数进行修改。
       //紧接着上方的onSelect={this.onSelect.bind(this)}
      selectedKeys={this.state.selectedKeys}//(受控)设置选中的树节点, selectedKeys需要是array类型的数据
     >
       {this.renderTreeNodes(treeData)} //树的结点采用一层一层循环嵌套的方式进行的,先进行父节点的调用,如果此父节点有chidren属性,则再次调用renderTreeNodes方法,依次循环。
 </Tree>

//以下代码需要放在render外面
//函数开始
onSelect(selectedKeys, info) {
        let { expandedKeys } = this.state;
        // console.log("onSelect", selectedKeys, info);
        let nameList = selectedKeys.length > 0 ? selectedKeys[0].split('-') : []
        if (nameList.length == 2) {		//通过判断节点是父节点还是子节点判断是否调用onExpend函数,是父节点就将点击的父节点放到expandedKeys 列表中,并调用onExpend,否则根据点击子节点的信息调用url 页面。
            if (expandedKeys.indexOf(selectedKeys[0]) == -1) {
                expandedKeys.push(selectedKeys[0])
                this.setState({ expandedKeys: expandedKeys }, () => {
                    this.onExpand(this.state.expandedKeys)
                })
                return;
            }
            let keylist = []
            for (let i of expandedKeys) {
                if (i == selectedKeys[0]) {
                }
                else {
                    keylist.push(i)
                }
            }
            // console.log(keylist)
            this.setState({ expandedKeys: keylist })
            this.onExpand(keylist)
        }
        else {
            if (nameList.length == 3) {
                //此处根据个人情况进行编写进行的操作就可以了
            }
        }

    };
 //函数结束

onSelect函数 需要对selectedKeys进行判断(我设置的父节点key是“0-0”,子节点key是“0-0-0”),可以根当前的key进行父子节点的判断,如果是父节点,就给expandedKeys重新赋值后调用onExpand函数对点击的节点进行展开,如果是子节点,就根据获取info.selectedNodes[0].props中的内容进行更新this.state中的内容。

//renderTreeNodes方法如下:
//函数开始
 renderTreeNodes(data) {
        let treedatas = data.map(item => {
            if (item.children) {
                return (
                    <TreeNode title={item.title} key={item.key} dataRef={item}>
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return <TreeNode key={item.key} {...item} />;
        });
        return treedatas
    }
    
//函数结束


//onExpand函数和onCheck函数不需要进行改动
onExpand(expandedKeys) {
    console.log('onExpand', expandedKeys);
    // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    // or, you can remove all expanded children keys.
    this.setState({
      expandedKeys,
      autoExpandParent: false,
    });
  };

  onCheck (checkedKeys){
    console.log('onCheck', checkedKeys);
    this.setState({ checkedKeys });
  };

经过这些修改,基本上可以完成树形组件,注意,我设计的树形组件父类节点是可以多选,也就是可以同时展开多个父类节点,但是子类节点只能选择一个,如果想要可以选择多个子节点,可以查看antd design官网进行查看。

3. 一些初始化问题

在this.state中需要进行一些初始化操作,具体如下:
注意,expandedKeys,checkedKeys和selectedKeys在官网上明确要求是array类型,我试过改成字符串,会出现一些bug,不推荐对其类型进行修改。

 this.state = {
    expandedKeys: ['0-0-0', '0-0-1'],//根据自己的实际情况选择默认展开的父节点
    autoExpandParent: true,
    checkedKeys: ['0-0-0'], 
    selectedKeys: [],
  };

4. 效果图

最后放下我的效果图(类似的哈,大概结构都是一样的)
最终实现的效果

参考:

https://ant.design/index-cn

好的,以下是一个使用 React 实现的四层子节点树形控件的完整示例代码: ```javascript import React from 'react'; class TreeNode extends React.Component { constructor(props) { super(props); this.state = { expanded: false }; this.toggleExpand = this.toggleExpand.bind(this); } toggleExpand() { this.setState(prevState => ({ expanded: !prevState.expanded })); } render() { const { node } = this.props; const { expanded } = this.state; return ( <div> <div onClick={this.toggleExpand}>{node.name}</div> {expanded && node.children && node.children.map(childNode => ( <TreeNode key={childNode.id} node={childNode} /> ))} </div> ); } } class Tree extends React.Component { constructor(props) { super(props); this.state = { treeData: { id: 1, name: 'Root', children: [ { id: 2, name: 'Level 1, Node 1', children: [ { id: 3, name: 'Level 2, Node 1', children: [ { id: 4, name: 'Level 3, Node 1', children: [ { id: 5, name: 'Level 4, Node 1' }, { id: 6, name: 'Level 4, Node 2' } ] }, { id: 7, name: 'Level 3, Node 2', children: [ { id: 8, name: 'Level 4, Node 3' }, { id: 9, name: 'Level 4, Node 4' } ] } ] }, { id: 10, name: 'Level 2, Node 2', children: [ { id: 11, name: 'Level 3, Node 3', children: [ { id: 12, name: 'Level 4, Node 5' }, { id: 13, name: 'Level 4, Node 6' } ] }, { id: 14, name: 'Level 3, Node 4', children: [ { id: 15, name: 'Level 4, Node 7' }, { id: 16, name: 'Level 4, Node 8' } ] } ] } ] } ] } }; } render() { return <TreeNode node={this.state.treeData} />; } } export default Tree; ``` 在这个例子中,`TreeNode` 组件用于表示每个节点,并具有展开/折叠节点的功能。`Tree` 组件包含整个树形结构的数据,并将其传递给根节点。 这个树形控件有四个级别的子节点,其中每个节点可以展开和折叠其子节点。你可以将其用于显示任何具有分层结构的数据,例如目录结构、导航菜单或组织架构图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值