基于leftIndent将扁平化数组转换为仿react-vtree树形结构
基于leftIndent将扁平数组转换为树形结构
嘿,我来帮你搞定这个需求——通过节点的leftIndent属性把扁平数组转成嵌套树形结构,实现类似react-vtree库的文件夹树视图效果,这就给你拆解清楚~
需求核心
我们需要根据每个节点的leftIndent缩进值,判断节点的层级关系,把扁平化的数组转换成父子嵌套的树形结构,缩进值越大,层级越深。
输入输出示例
输入(扁平数组)
const from = [ { id: 1, data: { leftIndent: 0, text: 'L', }, }, { id: 2, data: { leftIndent: 18, text: 'M', }, }, { id: 3, data: { leftIndent: 0, text: 'X', }, }, { id: 4, data: { leftIndent: 18, text: 'Y', }, }, { id: 5, data: { leftIndent: 36, text: 'Z', }, }, { id: 6, data: { leftIndent: 36, text: 'S', }, }, ];
目标输出(树形结构)
注:原示例中第一个节点的id写成0是笔误,这里修正为和输入一致的1,逻辑更合理
const to = [ { id: 1, data: { leftIndent: 0, text: 'L', }, children: [ { id: 2, data: { leftIndent: 18, text: 'M', }, }, ], }, { id: 3, data: { leftIndent: 0, text: 'X', }, children: [ { id: 4, data: { leftIndent: 18, text: 'Y', }, children: [ { id: 5, data: { leftIndent: 36, text: 'Z', }, }, { id: 6, data: { leftIndent: 36, text: 'S', }, }, ], }, ], }, ];
实现思路
核心逻辑是用栈跟踪当前各层级的父节点:
- 假设缩进是固定步长(比如示例里的18),通过
leftIndent / 步长计算节点层级 - 用栈保存每个层级的最新父节点,栈的索引对应层级深度(索引0是顶层节点)
- 遍历节点时,找到对应层级的父节点,把当前节点挂载到父节点的
children数组里 - 顶层节点直接加入结果数组,同时更新栈的顶层记录
代码实现
function flatToTree(flatArray, indentStep = 18) { const tree = []; // 栈:保存各层级的最新父节点,索引对应层级 const parentStack = []; flatArray.forEach(node => { // 计算当前节点的层级 const currentLevel = node.data.leftIndent / indentStep; // 复制节点并初始化children,避免修改原数据 const newNode = { ...node, children: [] }; if (currentLevel === 0) { // 顶层节点,直接加入结果树 tree.push(newNode); // 更新栈:替换当前层级及以上的记录,确保后续子节点找对父节点 parentStack.splice(currentLevel, parentStack.length - currentLevel, newNode); } else { // 找到父节点:层级比当前小1的节点 const parentNode = parentStack[currentLevel - 1]; if (parentNode) { parentNode.children.push(newNode); // 更新栈:把当前节点设为对应层级的父节点,供后续子节点使用 parentStack.splice(currentLevel, parentStack.length - currentLevel, newNode); } } }); return tree; } // 测试示例 const from = [ { id: 1, data: { leftIndent: 0, text: 'L', }, }, { id: 2, data: { leftIndent: 18, text: 'M', }, }, { id: 3, data: { leftIndent: 0, text: 'X', }, }, { id: 4, data: { leftIndent: 18, text: 'Y', }, }, { id: 5, data: { leftIndent: 36, text: 'Z', }, }, { id: 6, data: { leftIndent: 36, text: 'S', }, }, ]; const resultTree = flatToTree(from); console.log(JSON.stringify(resultTree, null, 2));
代码说明
indentStep参数:默认是18,和示例的缩进步长匹配,如果你的项目里缩进步长不同,直接传对应数值即可- 栈的作用:确保每个层级的子节点都能找到最近的父节点,比如处理层级2的节点时,栈的索引1就是它的父节点(层级1)
- 节点复制:用
{...node, children: []}创建新节点,避免污染原数组的数据 - 兼容性:支持任意层级的缩进,只要
leftIndent是indentStep的整数倍,完全适配react-vtree的文件夹树结构逻辑
内容的提问来源于stack exchange,提问作者MrChe
相关产品推荐
相关产品推荐

