嵌套对象转HTML树形表格问题:父节点重复且不符预期
问题:嵌套对象转HTML表格时父节点重复,树形结构不符合预期
我需要把嵌套对象映射成HTML表格,实现父子数据的树形结构,但现在的结果里父节点重复,而且树形数据没达到预期效果。
当前输出结果
ID Name 1 A.1 1.1 A.1.1 1.1.1 A.1.1.1 1.1.1.1 A.1.1.1.1 1 A.1 1.1 A.1.1 1.1.2 A.1.1.1 1.1.1.1 A.1.1.1.1 1 A.1 1.1 A.1.1 1.1.1 A.1.1.1 1.1.1.1 A.1.1.1.1 1 A.1 1.1 A.1.1 1.1.1 A.1.1.1 1.1.1.1 A.1.1.1.1 1 B.1 1.1 B.1.1 1.1.1 B.1.1.1 1.1.1.1 A.1.1.1.1 1 B.1 1.1 B.1.1 1.1.2 B.1.1.1 1.1.1.1 A.1.1.1.1 1 B.1 1.1 B.1.1 1.1.1 B.1.1.1 1.1.1.1 A.1.1.1.1 1 B.1 1.1 B.1.1 1.1.1 B.1.1.1 1.1.1.1 A.1.1.1.1
预期表格结果
| ID | Name | |----------|--------------| | "1" | "A.1" | | "1.1" | "A.1.1" | | "1.1.1" | "A.1.1.1" | | "1.1.2" | "A.1.1.2" | | "1.1.1.1"| "A.1.1.1.1" | | "1.1.1.1"| "A.1.1.1.2" | | "2" | "B.1" | | "1.1" | "B.1.1" | | "1.1.1" | "B.1.1.1" | | "1.1.2" | "B.1.1.2" | | "1.1.1.1"| "B.1.1.1.1" | | "1.1.1.1"| "B.1.1.1.2" |
问题代码
import "./styles.css"; const datas = { A: { id: "1", name: "A.1", child: { A1: { id: "1.1", name: "A.1.1", child: { A11: { id: "1.1.1", name: "A.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } }, A12: { id: "1.1.2", name: "A.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } } } }, A2: { id: "1.1", name: "A.1.1", child: { A11: { id: "1.1.1", name: "A.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } }, A12: { id: "1.1.1", name: "A.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } } } } } }, B: { id: "1", name: "B.1", child: { B1: { id: "1.1", name: "B.1.1", child: { B11: { id: "1.1.1", name: "B.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } }, B12: { id: "1.1.2", name: "B.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } } } }, B2: { id: "1.1", name: "B.1.1", child: { B11: { id: "1.1.1", name: "B.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } }, B12: { id: "1.1.1", name: "B.1.1.1", child: { A111: { id: "1.1.1.1", name: "A.1.1.1.1" } } } } } } } }; export default function App() { const renderRows = (parentData, dataArr = []) => { const newDataArr = [ ...dataArr, <tr> <td>{parentData.id}</td> <td>{parentData.name}</td> </tr> ]; if (!parentData.child) return newDataArr; return Object.values(parentData.child).map((child) => renderRows(child, newDataArr) ); }; return ( <div className="App"> <h1>Hello CodeSandbox</h1> <table> <thead> <tr> <td>ID</td> <td>Name</td> </tr> </thead> <tbody>{Object.values(datas).map((data) => renderRows(data))}</tbody> </table> </div> ); }
解决方法
问题出在renderRows函数的递归逻辑上:每次处理子节点时,你都把当前父节点的数组newDataArr传递给每个子节点的递归调用,导致每个子节点都会重复携带父节点的所有行,最终输出大量重复内容。
正确的做法是先添加当前节点,再递归合并所有子节点的结果,而不是把当前数组传递给每个子节点。修改后的renderRows函数如下:
const renderRows = (parentData) => { // 先创建当前节点的行,添加key避免React警告 const rows = [ <tr key={`${parentData.id}-${parentData.name}`}> <td>{parentData.id}</td> <td>{parentData.name}</td> </tr> ]; // 如果有子节点,递归处理每个子节点并合并结果 if (parentData.child) { Object.values(parentData.child).forEach(child => { rows.push(...renderRows(child)); }); } return rows; };
另外,你的数据源里存在一些和预期不符的字段(比如A12的name是"A.1.1.1"而不是预期的"A.1.1.2"),需要先修正数据源的错误,才能得到完全符合预期的结果:
// 修正后的部分数据源示例 A12: { id: "1.1.2", name: "A.1.1.2", // 原先是"A.1.1.1" child: { A111: { id: "1.1.1.1", name: "A.1.1.1.2" // 原先是"A.1.1.1.1" } } }
修改后,渲染逻辑会正确遍历每个节点一次,不会重复输出父节点,同时修正数据源后就能得到你预期的表格结构。
内容的提问来源于stack exchange,提问作者rzr
相关产品推荐
相关产品推荐

