ReactJS中的递归树视图

时间:2018-01-09 21:16:51

标签: reactjs

我试图用ReactJS从JSON数据中实现树视图,我完成了大部分工作但是我的扩展和折叠按钮有问题。正如现在单击其中一个子树节点成功扩展整个树时,问题是根据组件的状态(折叠/展开)我想更改图标。有人能帮助我吗?

import React from 'react';
import {IconExpand, IconCollapse} from '../components/Icons';

export default class Tree extends React.Component{
    constructor(props){
        super(props);
        const me = this;
        me.state = {
            visible: true
        };
        me.listItem = null;
        me.isVisible = me.isVisible.bind(me);
    }

    render(){
        const me = this;
        const {visible} = me.state;
        const {jsonData} = me.props;

        let keys = [];
        for (const key in jsonData) {
            if (jsonData.hasOwnProperty(key)) {
                keys.push(key);
            }
        }

        return (
            <ul className="x-tree">
                {keys.map((key, index) => {
                    if(jsonData[key] && typeof jsonData[key] === 'object'){
                        return (
                            <li 
                                className="x-tree-item x-tree-item-node"
                                key={`complex-${key}-${index}`}
                                ref={el => { me.listItem = el; }}
                            >
                                {visible
                                    ? <IconCollapse
                                        className="x-tree-icon"
                                    />
                                    : <IconExpand
                                        className="x-tree-icon"
                                    />
                                }
                                <span
                                    className="x-tree-key"
                                    onClick={me.onClick.bind(me)}
                                >
                                    {key}
                                </span>
                                <Tree
                                    jsonData={jsonData[key]}
                                    expanded={true}
                                />
                            </li>
                        )
                    } else {
                        return (
                            <li 
                                className="x-tree-item"
                                key={`simple-${key}-${index}`}
                            >
                                <span className="x-tree-key">{key}:     </span>
                                <span className="x-tree-value">    {jsonData[key]}</span>
                            </li>
                        )
                    }
                })}
            </ul>
        );
    }

    onClick(event){
        const me = this;
        let node = event.currentTarget;
        let tree = node.nextSibling;
        tree.style.display = tree.style.display === 'none' ? 'block' :     'none';
        me.setState({
            visible: !me.state.visible
        });
        me.isVisible(tree.style.display !== 'none');
    }

    isVisible(key){ 
        return key;
    }
}

2 个答案:

答案 0 :(得分:1)

有些事情是这样的:

class Tree extends React.Component{
  constructor(props){
      super(props);
      const me = this;
      me.state = {selected: (new Map(): Map<string, boolean>)};
      me.listItem = null;
  }

  render(){
      const me = this;
      const {visible} = me.state;
      const {jsonData} = me.props;

      let keys = [];
      for (const key in jsonData) {
          if (jsonData.hasOwnProperty(key)) {
              keys.push(key);
          }
      }

      return (
          <ul className="x-tree">
              {keys.map((key, index) => {
                  if(jsonData[key] && typeof jsonData[key] === 'object'){
                      return (
                         <li 
                          className="x-tree-item x-tree-item-node"
                          key={`complex-${key}-${index}`}
                          ref={el => { me.listItem = el; }}
                         > 

                          <span
                              className="x-tree-key"
                              onClick={me.onClick.bind(me)}
                              id={key}
                          >
                                {!!me.state.selected.get(key)
                                ? <IconCollapse  
                                    className="x-tree-icon"
                                />
                                : <IconExpand
                                    className="x-tree-icon"
                                />
                            }
                              {key}
                          </span>
                          <Tree
                              jsonData={jsonData[key]}
                              expanded={true}
                          />
                      </li>
                      )
                  } else {
                      return (
                          <li 
                              className="x-tree-item"
                              key={`simple-${key}-${index}`}
                          >
                              <span className="x-tree-key">{key}:     </span>
                              <span className="x-tree-value">    {jsonData[key]}</span>
                          </li>
                      )
                  }
              })}
          </ul>
      );
  }

  onClick(event){
      const me = this;
      let node = event.currentTarget;
      let tree = node.nextSibling;
      console.log(node.id);
      tree.style.display = tree.style.display === 'none' ? 'block' :     'none';
      this.setState((state) => {
        const selected = new Map(state.selected);
        selected.set(node.id, !selected.get(node.id)); // toggle
        return {selected};
      });

  }

}

答案 1 :(得分:0)

你应该为每个节点添加一个状态,因为它现在是整个树的visible状态

树组件的所有节点都具有相同的表达式

{visible ? <IconCollapse className="x-tree-icon" /> : <IconExpand  className="x-tree-icon" /> }

并且表达式visible对于每个<li>节点具有相同的值,因此您的组件对于特定树级别中的所有节点都有一个状态visible