【问题标题】:Loop through object with unkown levels of children in Preact在 React 中循环遍历具有未知子级的对象
【发布时间】:2018-06-20 15:25:09
【问题描述】:

我试图遍历一个有孩子的对象,可以有孩子,可以有孩子。

基本上我不知道对象可以包含多少子元素和级别。有没有一种简单的方法可以遍历这些,并在列表视图中渲染出一个组件,而不必在彼此旁边多次调用Object.keys(myobject).map。在渲染函数内部?

parent: {
  term: "cats",
  children: {
    child: {
      term: "kids", 
      otherdata: "dekme", 
      children: {
        granddaughter: {term: "kids", otherdata: "dekme"},
        grandson: {term: "mip", some other data: "si"}
      }
   },


  }
}

而且输出应该是这样的:

<ul>
  <li>
    <a href="">Parent</a>
      <ul>
        <li><a href="">child</a></li>
        <li><a href="">child</a>
          <ul>
            <li><a href="">grandkid</a>
            </li>
          </ul>
        </li>
      </ul>
  </li>
</ul>

【问题讨论】:

    标签: preact


    【解决方案1】:

    好问题!这类问题通常称为walking / tree walk,npm 上可能有一些很棒的库,您可以使用它们来简化它。不过,我们可以手动编写一个简单的递归。我假设您包含子元素的嵌套对象如下所示:

    var treeOfObjects = {
      children: [
        {
          name: 'billy'
        },
        {
          name: 'wanda',
          children: [
            {
              name: 'stanley'
            }
          ]
        }
      ]
    };
    

    这是一个遍历该树的 walk 函数,在它找到的每个子节点上调用您提供的 iterator 函数,并将结果收集到一个数组中。

    function walk(object, iterator, results) {
      // no results array it means we're at the root.
      // create the shared array, then map the root through our iterator.
      if (!results) {
        results = [iterator(object, null, object)];
      }
    
      if (object.children) {
        for (let i=0; i<object.children.length; i++) {
          // call the iterator on this child and append the result:
          let value = object.children[i];
          results.push(iterator(value, i, object));
    
          // now "walk into" the child object (appending its children, etc):
          walk(value, iterator, results);
        }
      }
      return results;
    }
    

    这是它在实践中的样子:

    class Foo extends Component {
      render({ someTreeOfObjects }) {
        return (
          <ul>
            {walk(someTreeOfObjects, object => (
              <li>{object.name}</li>
            ))}
          </ul>
        );
      }
    }
    // render(<Foo someTreeOfObjects={treeOfObjects} />)
    // .. produces: 
    // <ul>
    //   <li>billy</li>
    //   <li>wanda</li>
    //   <li>stanley</li>
    // </ul>
    

    更新 - 用于嵌套输出:

    function nodeToListItem (object) {
      // if we have children, we'll recurse into them
      const children = object.children || [];
      return (
        <li>
          {object.name}
          {children.length>0 && (
            <ul>
              {children.map(nodeToListItem)}
            <ul>
          )}
        </li>
      );
    }
    
    class Foo extends Component {
      render({ someTreeOfObjects }) {
        return (
          <ul>
            {nodeToListItem(someTreeOfObjects)}
          </ul>
        );
      }
    }
    

    因为原始结构的嵌套与我们想要在 DOM 中生成的内容相匹配,所以这最终是一个简单的图形转换。

    【讨论】:

    • 嘿,谢谢。我还需要为每个级别的孩子添加一个 ul。我也会用数据结构更新问题。
    • 哦,这更容易!在这些库中,您实际上可以传递大量嵌套的子数组。我会更新我的答案。
    猜你喜欢
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 2020-06-09
    • 2023-03-06
    相关资源
    最近更新 更多