我有一个前端 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/