You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:57:48