react.createElement如何根据json递归生成dom

发布于 2022-09-06 21:43:26 字数 1136 浏览 21 评论 0

现在要开发一个网站,要根据数据库里保存的节点ID生成前端页面,比如:json数据为:

let data=[
    {"id":1,"pid":0,"type":"div"},
    {"id":2,"pid":1,"type":"ul"},
    {"id":3,"pid":2,"type":"li"},
    {"id":4,"pid":3,"type":"span"},
    {"id":5,"pid":0,"type":"div"},
    ...
]

一个常规前端页面的data结果应该有几百个数组元素,pid为父节点id,如果为顶级节点(即body标签的直接子节点),pid=0;

data.map((evt,i)=>{
    React.cteateElement('div',{},[children...]);
})

实际数据比这个复杂,需要判断节点类型,是生成div还是ul,span或其他标签,用JSX语法解决不了这个创建问题。因为节点类型取自data里面的type,有多少层嵌套也是未知的,根据json结果而变化。
最后生成的页面可能是这样:

<div data-id="1" data-pid="0"></div>
<div data-id="2" data-pid="0">
    <div data-id="3" data-pid="2">
        <ul data-id="5" data-pid="3">
            <li data-id="6" data-pid="5">
                <!--里面更多节点或直接是文本内容-->
            </li>
            <li data-id="7" data-pid="5"></li>
        </ul>
    </div>
    <div data-id="4" data-pid="2"></div>
</div>

如何把一个非顶级节点插入到children里面,如果一个顶级节点嵌套有多级子节点,感觉需要用递归,这个递归要如何写在createElement里面,一点头绪没有,求大神帮忙。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尐籹人 2022-09-13 21:43:26

cteateElement 的时候就应该把 children 准备好了
所以应该从子到父创建实例

需要2个递归

  • 第一个递归用来整理 json
  • 第二个用来创建实例

参考下面代码:

class App extends React.Component {
  constructor() {
    super()
    this.badJson = [
      {id: 1, pid: 0, type: 'div'},
      {id: 2, pid: 1, type: 'ul'},
      {id: 3, pid: 2, type: 'li'},
      {id: 4, pid: 3, type: 'span'},
      {id: 5, pid: 0, type: 'div'}
    ]
  }

  handleJson(val, pid) {
    if (val.pid == pid) {
      const children = this.badJson.map(val2 => this.handleJson(val2, val.id)).filter(x => x)
      if (children.length) val.children = children
      return val
    }
  }

  createNodes({id, pid, children, type}) {
    return React.createElement(
      type || 'div',
      {key: id},
      children ? children.map(val => this.createNodes(val)) : id
    )
  }

  render() {
    // 处理 JSON
    const goodJson = this.badJson.map(val => this.handleJson(val, 0)).filter(x => x)

    return <div>{goodJson.map(val => this.createNodes(val))}</div>
  }
}
甜心小果奶 2022-09-13 21:43:26

你能说说jsx语法为什么解决不了这个问题呢?
根据你提供的样例,第一、二层都是div,第三层是ul,第四层是li
然后通过map return出来就可以了。都不需要递归。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文