在开发项目中,可能常见后端返回一个扁平的一维数组,前端可能要处理数据将其转化为 tree 型结构。类似:

const data = [{
    id: 1,
    parentId: null
  },
  {
    id: 2,
    parentId: 1
  },
  {
    id: 3,
    parentId: 1
  },
  {
    id: 4,
    parentId: 2
  },
  {
    id: 5,
    parentId: 4
  }
];

TO

{
  id: 1,
  parentId: null,
  children: [{
    id: 2,
    parentId: 1,
    children: [{
      id: 4,
      parentId: 2,
      children: [{
        id: 5,
        parentId: 4,
      }]
    }]
  }, {
    id: 3,
    parentId: 1
  }]
}

解决思路如下:

递归处理处理法

// 极简
const toTree = (items, id = null, link = 'parentId') =>
  items
  .filter(item => item[link] == id)
  .map(item => ({
    ...item,
    children: toTree(items, item.id)
  }));

这里最终返回的是数组,可以加个 result = toTree(data)[0]

对象引用法

function toTree(data) {
  const idMapping = data.reduce((acc, el, i) => {
    acc[el.id] = i;
    return acc;
  }, {});

  let root;
  data.forEach(el => {
    // 判断根节点
    if (el.parentId === null) {
      root = el;
      return;
    }
    // 用映射表找到父元素
    const parentEl = data[idMapping[el.parentId]];
    // 把当前元素添加到父元素的`children`数组中
    parentEl.children = [...(parentEl.children || []), el];
  });
  return root
}