好问题!这类问题通常称为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 中生成的内容相匹配,所以这最终是一个简单的图形转换。