javascript - 如何从表示嵌套树的物化路径数组遍历并渲染嵌套 HTML?

标签 javascript reactjs tree nested jsx

我有一个前端 React 组件在 AJAX 调用后收到的数组。该数组只是从后端发送的带注释的列表,代表 Django-Treebeard 模型数据。带注释的列表是一个物化路径树,它以平面数组的形式构造嵌套树的所有节点。

以下是前端react中可用的确切数据:

const data = [
  {
    info: { close: [], open: true, level: 1 },
    spot: {
      id: 2,
      path: "00020002",
      depth: 2,
      numchild: 0,
      landmark_name: "Metrolink Trafford Depot",
      distance: "700.00",
      unit: "m",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 3,
      path: "00020003",
      depth: 2,
      numchild: 0,
      landmark_name: "Bus Stand",
      distance: "300.00",
      unit: "m",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 4,
      path: "00020005",
      depth: 2,
      numchild: 2,
      landmark_name: "Restaurants and Bars",
      distance: null,
      unit: null,
      child: 1
    }
  },
  {
    info: { close: [], open: true, level: 2 },
    spot: {
      id: 5,
      path: "000200050001",
      depth: 3,
      numchild: 2,
      landmark_name: "Trafford Bar",
      distance: 650.00,
      unit: "m",
      child: 1
    }
  },
  {
    info: { close: ["0"], open: false, level: 2 },
    spot: {
      id: 6,
      path: "000200050003",
      depth: 3,
      numchild: 0,
      landmark_name: "Café Hardrock",
      distance: "1.50 ",
      unit: "km",
      child: 0
    }
  },
  {
    info: { close: [], open: false, level: 1 },
    spot: {
      id: 8,
      path: "00020008",
      depth: 2,
      numchild: 1,
      landmark_name: "Hospital",
      distance: null,
      unit: null,
      child: 1
    }
  },
  {
    info: { close: ["0", "1", "2"], open: true, level: 2 },
    spot: {
      id: 14,
      path: "000200080001",
      depth: 3,
      numchild: 0,
      landmark_name: "Seymour Grove Health Centre",
      distance: "320.00",
      unit: "m",
      child: 0
    }
  }
];

后端实际的数据树是:

Root
|_ Metrolink Trafford Depot: 700m
|_Bus Stand: 300 
|_Restaurant and Bars:
  |_Trafford Bar : 650m
  |_ Café Hardrock: 1.5km
|_ Hospital:
  |_ Seymour Grove Health Centre: 320m

我想创建代表上述层次结构的嵌套 div 结构,如下所示:

<div>
    <h3> MetroLink Trafford Depot :</h3>
    <p> 700m </p>
</div>
<div>
    <h3> Bus Stand:</h3>
    <p>300m </p>
</div>
<div>
    <h3> Restaurants and Bars:</h3>
        <div>
            <h4> Trafford Bar:</h4>
            <p> 650m</p>
        </div>
        <div>
            <h4> Café Hardrock:</h4>
            <p> 1.5km</p>
        </div>
</div>
<div>
    <h3> Hospital:</h3>
        <div> 
            <h4> Seymour Grove Health Centre:</h4>
            <p>320m</p>
        </div>
</div>

我尝试过递归,但惨败。甚至与我的意图相差甚远。 我尝试搜索第三方解决方案,但它们需要完全不同的数据结构。我不想改变后端的数据结构。这是我刚刚经历的另一个 hell 。另外我认为物化路径树更适合后端效率。

如何编写 React 组件来根据给定数据生成上述 HTML 结构?

最佳答案

您可以首先使用 path 属性从中创建一个嵌套对象结构(将其分割为 4 个字符的 block )。一旦完成,您就可以使用递归来创建 HTML 元素:

class Tree extends React.Component {
    constructor(props) {
        super(props);
        this.state = { data: props.data }
    }
    render() {
        // Create nested tree structure from data
        let root = { children: {} };
        for (let {spot} of this.state.data) {
            let node = root;
            for (let child of spot.path.match(/..../g)) {
                if (!(child in node.children)) node.children[child] = { children: {} };
                node = node.children[child];
            }
            node.name = spot.landmark_name;
            if (spot.distance) node.distance = String(+spot.distance) + spot.unit;
        }
        // Create elements from tree
        const e = React.createElement;
        return (function recur(node, level=1) {
            let children = Object.values(node.children).map(child => recur(child, level+1));
            if (children.length === 1 && !node.name) return children[0];
            if (!children.length) children = [e("p", null, node.distance)];
            if (node.name) children.unshift(e("h" + level, null, node.name));
            return e("div", null, ...children);
        })(root);
    }
}

// Sample data from the question:
const data = [{info: { close: [], open: true, level: 1 },spot: {id: 2,path: "00020002",depth: 2,numchild: 0,landmark_name: "Metrolink Trafford Depot",distance: "700.00",unit: "m",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 3,path: "00020003",depth: 2,numchild: 0,landmark_name: "Bus Stand",distance: "300.00",unit: "m",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 4,path: "00020005",depth: 2,numchild: 2,landmark_name: "Restaurants and Bars",distance: null,unit: null,child: 1}},{info: { close: [], open: true, level: 2 },spot: {id: 5,path: "000200050001",depth: 3,numchild: 2,landmark_name: "Trafford Bar",distance: 650.00,unit: "m",child: 1}},{info: { close: ["0"], open: false, level: 2 },spot: {id: 6,path: "000200050003",depth: 3,numchild: 0,landmark_name: "Café Hardrock",distance: "1.50 ",unit: "km",child: 0}},{info: { close: [], open: false, level: 1 },spot: {id: 8,path: "00020008",depth: 2,numchild: 1,landmark_name: "Hospital",distance: null,unit: null,child: 1}},{info: { close: ["0", "1", "2"], open: true, level: 2 },spot: {id: 14,path: "000200080001",depth: 3,numchild: 0,landmark_name: "Seymour Grove Health Centre",distance: "320.00",unit: "m",child: 0}}];

// Render
ReactDOM.render(React.createElement(Tree, {data}), document.body);
div, p { margin-left: 20px }
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

关于javascript - 如何从表示嵌套树的物化路径数组遍历并渲染嵌套 HTML?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57007329/

相关文章:

javascript - 如何在javascript中对对象的这个对象中的值求和?

reactjs - 使用 jest 对 axios post 进行单元测试

tree - "Borrowed value does not live long enough"在 B-Tree 节点枚举上匹配以获取引用时

python - 在 python 中定义和遍历树的有效方法是什么?

javascript - 如何减慢函数内的 onclick 事件或使其逐渐发生?寻求平稳过渡

javascript - 单页 Web 应用程序 (SPA) 链接/刷新路由设计注意事项和缓存

javascript - Node CSV 解析器,异步流式传输,逐行读取,并且能够暂停和恢复流式传输

reactjs - 如何更改在选择时打开的 Material ui 弹出窗口高度

javascript - react : this is null in event handler

algorithm - 平衡的树和空间和时间的权衡