React:递归渲染嵌套元素

时间:2016-01-19 01:49:27

标签: javascript reactjs

我提前为代码格式化道歉。 我有这样的数据源:

answer

使用React,我尝试将其转换为var data = { key1: 'value', key2: 123, key3: { key30: 'value', key31: { key310: 123, key311: 'hello' } } } ,如下所示:

<ul>

到目前为止,我已经尝试过了:

<ul id="data">
<li>key1: value</li>
<li>key2: 123</li>
<li>key3: [Object]
 <ul>
  <li>key30: value</li>
  <li>key31: [Object]
   <ul><li>key310: 123</li>
   <li>key311: hello</li>
   </ul>
  </li>
 </ul>
</li>
</ul>

它解析整个树,但它不会在正确的容器中呈现元素。

2 个答案:

答案 0 :(得分:7)

以下是来自https://github.com/calitek/ReactPatterns React.14.Common / TreeView的嵌套树的示例。请注意,在这种情况下,嵌套属性是子项。

&#13;
&#13;
import React from 'react';
import lodashGet from 'lodash/object/get';

let TreeRootSty = {lineHeight: '120%'}
let liSty = {listStyleType: 'none'};
let ulSty = {height: 'inherit', WebkitPaddingStart: '16px'};
let ulStyle = {height: 'inherit', WebkitPaddingStart: '16px'};
let iconSty = {marginRight: '10px', width: '16px'};

let nottogglable = {
  color: '#FFF',
  cursor: 'pointer',
  margin: '0 0 0 .8em'
};

let togglable = {
  color: '#815C7C',
  cursor: 'pointer',
  margin: '0'
};

let options = {};

let getTreeNode = function(child, index) {
  return <li key={index} style={liSty}><JTreeViewNode node={child} iconClick={this.props.iconClick} titleClick={this.props.titleClick} /></li>;
};

class JTreeViewNode extends React.Component {
  constructor(props) { super(); }
  iconHandler = () => {
    if (this.props.node.children && this.props.node.children.length > 0) {
      this.props.iconClick(this.props.node);
    } else {
      this.clickHandler();
    }
  };
  clickHandler = () => { this.props.titleClick(this.props.node); };
  render() {
    let titleSty = {color: '#afac87', marginTop: '2px'};
    let childNodes;
    let pSty = nottogglable;

    if (this.props.node.children && this.props.node.children.length > 0) {
      childNodes = this.props.node.children.map(getTreeNode, this);
      titleSty.color = this.props.node.selected ? '#7BB53B' : '#AF90A5';
    } else {
      titleSty.color = this.props.node.selected ? '#b58900' : '#afac87';
    }

    let isClosed = true;
    if (this.props.node.closed != null) isClosed = this.props.node.closed;

    let branch = (
      <ul id='ulStyle' style={ulStyle}>
        {childNodes}
      </ul>
    )
    if (isClosed) branch = null;

    let props = this.props;
    let iconType = lodashGet(props, options.typeName);
    if (iconType == options.icon.sun) iconSty.background = "url('./img/sun.ico') 0/16px no-repeat !important";
    else if (iconType == options.icon.leaf) iconSty.background = "url('./img/leaf.ico') 0/16px no-repeat !important";
    else if (iconType == options.icon.snow) iconSty.background = "url('./img/snow.ico') 0/16px no-repeat !important";
    else iconSty.background = "url('./img/sun.ico') 0/16px no-repeat !important";

    return (
      <div id='TreeNode'>
        <div id='pSty' style={pSty} className='FlexBox'>
          <div id='iconSty' onClick={this.iconHandler} style={iconSty}>&nbsp;</div>
          <div id='titleSty' onClick={this.clickHandler} style={titleSty} >
            {this.props.node.title}
          </div>
        </div>
        {branch}
      </div>
    );
  }
}

export default class JTreeView extends React.Component {
  render() {
    options = this.props.options;
    let childNodes = this.props.data.map(getTreeNode, this);
    return (
      <div id='TreeRootSty' style={TreeRootSty}>
        <ul id='ulSty' style={ulSty}>
            {childNodes}
        </ul>
      </div>
    );
  }
}
&#13;
&#13;
&#13;

答案 1 :(得分:1)

我有类似的问题,这是一个解决方案;希望它有所帮助。

&#13;
&#13;
const dummyData= Immutable.fromJS(
               {Id:10203040,
                birdIs: "The Word",
                contains:{
                  USER_ID: 219038012,
                  FirstName:"John",
                  LastName:"Smith",
                  Username:"JSmith",
                  PassWord:"pass",
                  strings:{one: "Red Phis", blue:"Blue Phis"}
                },
                number:1337,
                lists:{
                  a: 1,
                  b: 2,
                  c: 3
                },
                closer:"closed"
              })


class NestedListDisplay extends React.Component {

  deepDisplay(items){
    var newItems = []
    for (let [key, entry] of items ){
      newItems[newItems.length] = (this.checker(entry, key))
    }
    return newItems
  }

  checker(entry, liKey) {
    switch (typeof entry){
      case 'object':
        return <ul key={liKey}> {this.deepDisplay(entry)} </ul>
      case 'list':
        return <ul key={liKey}> {this.deepDisplay(entry)} </ul>
      case 'number':
        return <li key={liKey}> {entry} </li>
      case 'string':
        return <li key={liKey}> {entry} </li>
    }
  }

  render() {
    return (
      <div>
        <h1>Nested List Display</h1>
        <ul> {this.deepDisplay(dummyData)} </ul>
      </div>
    )
  }
}
    
ReactDOM.render(
    <NestedListDisplay />,
  document.getElementById('app')
)
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.7.2/immutable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<body>
  <div id="app"></div>
</body>
&#13;
&#13;
&#13;

注意 - 我使用Immutable.js来创建dummyData iterable