鍍金池/ 問(wèn)答/網(wǎng)絡(luò)安全  HTML/ react.createElement如何根據(jù)json遞歸生成dom

react.createElement如何根據(jù)json遞歸生成dom

現(xiàn)在要開(kāi)發(fā)一個(gè)網(wǎng)站,要根據(jù)數(shù)據(jù)庫(kù)里保存的節(jié)點(diǎn)ID生成前端頁(yè)面,比如:json數(shù)據(jù)為:

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"},
    ...
]

一個(gè)常規(guī)前端頁(yè)面的data結(jié)果應(yīng)該有幾百個(gè)數(shù)組元素,pid為父節(jié)點(diǎn)id,如果為頂級(jí)節(jié)點(diǎn)(即body標(biāo)簽的直接子節(jié)點(diǎn)),pid=0;

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

實(shí)際數(shù)據(jù)比這個(gè)復(fù)雜,需要判斷節(jié)點(diǎn)類(lèi)型,是生成div還是ul,span或其他標(biāo)簽,用JSX語(yǔ)法解決不了這個(gè)創(chuàng)建問(wèn)題。因?yàn)楣?jié)點(diǎn)類(lèi)型取自data里面的type,有多少層嵌套也是未知的,根據(jù)json結(jié)果而變化。
最后生成的頁(yè)面可能是這樣:

<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">
                <!--里面更多節(jié)點(diǎn)或直接是文本內(nèi)容-->
            </li>
            <li data-id="7" data-pid="5"></li>
        </ul>
    </div>
    <div data-id="4" data-pid="2"></div>
</div>

如何把一個(gè)非頂級(jí)節(jié)點(diǎn)插入到children里面,如果一個(gè)頂級(jí)節(jié)點(diǎn)嵌套有多級(jí)子節(jié)點(diǎn),感覺(jué)需要用遞歸,這個(gè)遞歸要如何寫(xiě)在createElement里面,一點(diǎn)頭緒沒(méi)有,求大神幫忙。

回答
編輯回答
不歸路

cteateElement 的時(shí)候就應(yīng)該把 children 準(zhǔn)備好了
所以應(yīng)該從子到父創(chuàng)建實(shí)例

需要2個(gè)遞歸

  • 第一個(gè)遞歸用來(lái)整理 json
  • 第二個(gè)用來(lái)創(chuàng)建實(shí)例

參考下面代碼:

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>
  }
}
2018年2月28日 14:12
編輯回答
刮刮樂(lè)

你能說(shuō)說(shuō)jsx語(yǔ)法為什么解決不了這個(gè)問(wèn)題呢?
根據(jù)你提供的樣例,第一、二層都是div,第三層是ul,第四層是li。
然后通過(guò)map return出來(lái)就可以了。都不需要遞歸。

2018年7月4日 16:59