简体   繁体   English

树表-在react.js上设置子级

[英]Tree Table - Setting children on react.js

I'm trying to build a Tree Table that is capable of shown/hide their TR childs when clicked (among other things). 我正在尝试构建一个树表,该树表能够在单击时显示/隐藏其TR子级。

I've grab some code from the web to generate easily generate a tree structure. 我已经从网上获取了一些代码来轻松生成树结构。 The problem comes trying to set a parent/child relationship with this event. 问题来了,试图与此事件设置父/子关系。 I'm really not used to react so it is hard for me to understand certain things. 我真的不习惯做出反应,所以我很难理解某些事情。

This is the data structure: 这是数据结构:

var data = [
  {
    id: 1,
    label: 'Order 1',
    deep: 0,
    children: [{
      id: 11,
      label: 'Cycle November',
      deep: 1,
    },
    {
      id: 12,
      label: 'Cycle December',
      deep: 1,
    }]
  },
  {
    id: 2,
    label: 'Order 2',
    deep: 0,
    children: [{
      id: 21,
      label: 'Cycle January',
      deep: 1
    }]
  },
];

Then i want to click on Parent id 1 and see who their children are. 然后,我想单击“父母ID 1”,看看他们的孩子是谁。

This is the code that draws the Table: 这是绘制表格的代码:

var TR = React.createClass({
  childs: [],
  hasParent: function() {
    if (this.props.parent) {
      return true;
    }
    else {
      return false;
    }
  },
  componentDidMount: function(){
    if (this.hasParent()) {
      parentKey = this.props.parent.props.keyId.split('-')[1];
      thisKey   = this.props.keyId.split('-')[0];
      if (parentKey == thisKey) {
        console.log('I set the child'); 
        this.props.parent.props.childs.push(this);
      }
    }
  },
  handleClick: function(event) {
    if (this.hasParent()) {
      parent = this.props.parent;
      console.log('My father is: '+parent.props.keyId);
      console.log('Me and my brothers are: ');
      parent.props.childs.map(function(child) {
        console.log(child.props.keyId);
      });
    }
    else {
      console.log('I am: '+this.props.keyId);
      console.log('My children are:');
      this.props.childs.map(function(child) {
        console.log(child.props.keyId);
      });
    }
  },
  isShown: function() {
    return false;
  },
  getDefaultProps: function() {
      return {
        childs: new Array(),
      };
  },
  render: function() {
    var iparent = this.props.data.deep*20;

    return (
        <tr>
          <td style={{paddingLeft: iparent+'px'}}>
            <span onClick={this.handleClick} >
            &nbsp; + </span>
            {this.props.data.label}
          </td>
        </tr>
    );
  }
});

var Tree = React.createClass({
  render: function() {
    var treeItems = [];
    parent = null;
    var renderTreeItems = function(items, parent) {
      if (!items) {
        return;
      }
      for (var i = 0; i < items.length; i++) {
        if (items[i].deep == 0) {
          var parent_id = items[i].deep;
        }
        else {
          var parent_id = parent.props.data.id;
        }
        var key = parent_id+'-'+items[i].id;

        tr = (
          <TR key={key} keyId={key} data={items[i]} parent={parent} >
          </TR>
        );
        treeItems.push(
          tr
          );
        renderTreeItems(items[i].children, tr);
      }
    };
    renderTreeItems(this.props.data);
    return (
      <table>
        { treeItems }
      </table>
    );
  }
});

And last the HTML to attach the component: 最后是HTML来附加组件:

<html>
    <body>
        <div id="tree"></div>
        <script type="text/jsx">
            React.render(<Tree data={data}/>, document.body);
        </script>
    </body>
</html>

The actual problem is that childs (badly written i know...) seems to be shared between all TR instances. 实际的问题是,所有TR实例之间似乎共享了childs(我写得不好)。 Can someone point what i'm doing wrong and what is the best approach to deal with this? 有人可以指出我做错了什么,解决这个问题的最佳方法是什么? Simply: i want to hide/show childs clicking on the TR-First TD that "acts" as a parent. 简单地说:我想隐藏/显示单击“充当”父母的TR-First TD的孩子。

Here is the jsfiddle http://jsfiddle.net/69z2wepo/2731/ 这是jsfiddle http://jsfiddle.net/69z2wepo/2731/

I approached the problem from a new perspective using a parent_key on every TR and querying against all the array in search of those objects that have that parent_key , changing it's properties. 我从每个角度对每个TR使用parent_key并针对所有数组进行查询,以寻找具有该parent_key对象,从而更改其属性,从而从一个新的角度解决了这个问题。 Now I have the start of a fully functional table tree. 现在,我开始了一个功能齐全的表树。

//Won't work below IE9, but totally safe otherwise
!function() {
    function _dynamicSortMultiple(attr) {
       /*
        * save the arguments object as it will be overwritten
        * note that arguments object is an array-like object
        * consisting of the names of the properties to sort by
        */
       var props = arguments;
       return function (obj1, obj2) {
           var i = 0, result = 0, numberOfProperties = props.length;
           /* try getting a different result from 0 (equal)
            * as long as we have extra properties to compare
            */
           while(result === 0 && i < numberOfProperties) {
               result = _dynamicSort(props[i])(obj1, obj2);
               i++;
           }
           return result;
      };
    }
    function _dynamicSort(property) {
        var sortOrder = 1;
        if(property[0] === "-") {
            sortOrder = -1;
            property = property.substr(1);
        }
        return function (a,b) {
            var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
            return result * sortOrder;
        }
    }
    Object.defineProperty(Array.prototype, "sortBy", {
        enumerable: false,
        writable: true,
        value: function() {
            return this.sort(_dynamicSortMultiple.apply(null, arguments));
        }
    });
}();

var TD = React.createClass({
    onHandleClick: function(event) {
        this.props.onHandleClick(this.props.data.key);
    },
    render: function() {
        var iparent = this.props.data.deep*20;
        var icon = "fa-chevron-down";

        return (
            <td style={{paddingLeft: iparent+'px'}}>
                <span onClick={this.onHandleClick} className={"fa "+icon}>
                &nbsp;</span>
                {this.props.data.label}
            </td>
        );
    }
})

var TR = React.createClass({
  onHandleClick: function(TD) {
    this.props.onHandleClick(TD);
  },
  render: function() {
    if (this.props.data.isShown) {
        return (
        <tr>
            <TD data={this.props.data} onHandleClick={this.onHandleClick}/>
        </tr>
        );
    }
    else {
        return (
            <tr>
            </tr>
        );
    }
  }
});

var List = React.createClass({
  render: function() {
    var self = this;
    var trs = this.props.data.map(function(row) {
      var key = row.deep+'-'+row.id;
      return (<TR key={key} keyId={key} parentKey={row.parent_key} data={row} onHandleClick={self.props.onHandleClick} />);
    });

    return (
      <table>
        {trs}
      </table>
    );
  }
});

var Tree = React.createClass({
  handleClick: function(key) {
    newState = this.state.data.slice();
    for (var i = newState.length - 1; i >= 0; i--) {
        var item = newState[i];
        if (item.parent_key == key) {
            item.isShown = (item.isShown)?false:true;
            newState[i] = item;
        }
    };
    this.setState({data: newState});
  },
  loadFromServer: function() {
    var data = [
      {
        id: 1,
        label: 'Order 1',
        deep: 0,
        key: '0-1',
        parent_key: '0',
      },
      {
        id: 11,
        label: 'Cycle November',
        deep: 1,
        key: '0-1-11',
        parent_key: '0-1',
      },
      {
        id: 12,
        label: 'Cycle December',
        deep: 1,
        key: '0-1-12',
        parent_key: '0-1',
      },
      {
        id: 2,
        label: 'Order 2',
        deep: 0,
        key: '0-2',
        parent_key: '0'
      },
      {
        id: 21,
        label: 'Cycle January',
        deep: 1,
        key: '0-2-21',
        parent_key: '0-2',
      }
    ];
    newState = [];
    data.map(function(item) {
        item.isShown = (item.deep != 0)?false:true;
        newState.push(item);
    });
    newState.sortBy("key");
    this.setState({data:newState});
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadFromServer();
  },
  render: function() {
    return (
      <div className="Box">
        <table className="table table-striped table-hover dataTables-orders" >
          <thead>
          </thead>
          <List data={this.state.data} onHandleClick={this.handleClick} />
        </table>
      </div>
    );
  }
});
React.render(<Tree data={data}/>, document.getElementById('tree'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM