React中遍历Map生成JSX及构建树形UI的技术问询
在React中遍历Map生成JSX的两种场景实现
一、简单键值对Map的渲染
针对你给出的基础Map:
const map1 = new Map(); map1.set(0, 'foo'); map1.set(1, 'bar');
你可以利用Map.prototype.entries()获取所有键值对,转成数组后用React的map方法渲染JSX:
function SimpleMapRenderer() { const map1 = new Map(); map1.set(0, 'foo'); map1.set(1, 'bar'); // 把Map转成[[key, value], ...]格式的数组 const mapEntries = Array.from(map1.entries()); return ( <div> {mapEntries.map(([key, value]) => ( <div key={key}>{key}: {value}</div> ))} </div> ); }
渲染后就能得到你要的结果:
0: foo
1: bar
二、树形结构Map的前序遍历渲染
你当前的buildTreeMap函数只存了父节点对应的子节点列表,没关联节点自身的内容,不太方便渲染。先优化下树形结构的构建,把每个节点的完整数据和子节点绑定:
function buildTree(replies) { // 用Map存所有节点,通过id快速查找 const nodeMap = new Map(); replies.forEach(reply => { nodeMap.set(reply.id, { ...reply, children: [] }); }); // 给每个父节点挂载子节点 const rootNodes = []; replies.forEach(reply => { if (!reply.parentId) { rootNodes.push(nodeMap.get(reply.id)); } else { const parent = nodeMap.get(reply.parentId); if (parent) parent.children.push(nodeMap.get(reply.id)); } }); return rootNodes; }
这个函数会返回根节点数组(你的数据里只有一个根节点),每个节点自带children数组,接下来用递归组件实现前序遍历:
// 递归渲染单个节点及其子节点 function TreeNode({ node }) { return ( <div style={{ marginLeft: '16px' }}> {/* 先渲染当前节点(前序遍历:根 -> 子节点) */} <div>{node.body}</div> {/* 递归渲染所有子节点 */} {node.children.map(child => ( <TreeNode key={child.id} node={child} /> ))} </div> ); } // 树形结构容器组件 function TreeRenderer({ data }) { const rootNodes = buildTree(data.replies); return ( <div> {rootNodes.map(root => ( <TreeNode key={root.id} node={root} /> ))} </div> ); } // 使用方式 <TreeRenderer data={data} />
渲染后会得到层级清晰的树形UI:
hello here i am
test it out
hello there!
i dont continue testing
this cannot be tested
this is ridiculous
如果一定要用你原来的buildTreeMap生成的结构,那就得同时维护一个存所有节点的Map,再写递归遍历:
function buildTreeMap(replies) { const treeMap = new Map(); const nodeMap = new Map(); replies.forEach(reply => nodeMap.set(reply.id, reply)); for (const reply of replies) { const { id, parentId } = reply; if (!parentId) { treeMap.set(id, []); } else { if (!treeMap.has(parentId)) { treeMap.set(parentId, [reply]); } else { const children = treeMap.get(parentId); children.push(reply); treeMap.set(parentId, children); } } } return { treeMap, nodeMap }; } // 递归遍历渲染 function renderNode(nodeId, treeMap, nodeMap) { const node = nodeMap.get(nodeId); const children = treeMap.get(nodeId) || []; return ( <div key={nodeId} style={{ marginLeft: '16px' }}> <div>{node.body}</div> {children.map(child => renderNode(child.id, treeMap, nodeMap))} </div> ); } function TreeRenderer({ data }) { const { treeMap, nodeMap } = buildTreeMap(data.replies); const rootNode = data.replies.find(r => !r.parentId); return rootNode ? renderNode(rootNode.id, treeMap, nodeMap) : null; }
这样也能实现你要的树形渲染效果。
内容的提问来源于stack exchange,提问作者Geeky
相关产品推荐
相关产品推荐

