>[success] # 把原始 list 转换成树形结构 ~~~ 1.以下数据结构中,id 代表部门编号,name 是部门名称,parentId 是父部门 编号,为 0 代表一级部门,现在要求实现一个 convert 方法,把原始 list 转换 成树形结构,parentId 为多少就挂载在该 id 的属性 children 数组下 ~~~ ~~~ // 原始 list 如下 let list =[ {id:1,name:'部门A',parentId:0}, {id:2,name:'部门B',parentId:0}, {id:3,name:'部门C',parentId:1}, {id:4,name:'部门D',parentId:1}, {id:5,name:'部门E',parentId:2}, {id:6,name:'部门F',parentId:3}, {id:7,name:'部门G',parentId:2}, {id:8,name:'部门H',parentId:4} ]; const result = convert(list, ...); // 转换后的结果如下 let result = [ { id: 1, name: '部门A', parentId: 0, children: [ { id: 3, name: '部门C', parentId: 1, children: [ { id: 6, name: '部门F', parentId: 3 }, { id: 16, name: '部门L', parentId: 3 } ] }, { id: 4, name: '部门D', parentId: 1, children: [ { id: 8, name: '部门H', parentId: 4 } ] } ] }, ··· ]; ~~~ >[danger] ##### 用递归解决 ~~~ let list = [ { id: 4, name: "部门D", parentId: 1 }, { id: 5, name: "部门E", parentId: 2 }, { id: 6, name: "部门F", parentId: 3 }, { id: 7, name: "部门G", parentId: 2 }, { id: 1, name: "部门A", parentId: 0 }, { id: 2, name: "部门B", parentId: 0 }, { id: 3, name: "部门C", parentId: 1 }, { id: 8, name: "部门H", parentId: 4 }, ]; // 递归思路先找一个节点下的所有,即当前根节点为 0 // 就找到 第一个根节点中值为{ id: 1, name: "部门A", parentId: 0 } // 开始递归找到 当前id:1 节点的子节点,即其他parentId 为1的节点 // 依次开始当找到 { id: 4, name: "部门D", parentId: 1 } 第一个 // parentId 为1的节点继续递归去找 parentId 4 的节点 function convert(source, parentId = 0) { const ls = []; for (let item of source) { // 去找当前节点的子节点 if (parentId === item.parentId) { // 这些去找它的子节点 const rs = convert(source, item.id); // 把子节点拼接会现在节点 if (rs.length > 0) item.children = rs; ls.push(item); } } return ls; } console.log(convert(list)); ~~~ >[danger] ##### 使用两个filter 过滤 ~~~ let list = [ { id: 4, name: "部门D", parentId: 1 }, { id: 5, name: "部门E", parentId: 2 }, { id: 6, name: "部门F", parentId: 3 }, { id: 7, name: "部门G", parentId: 2 }, { id: 1, name: "部门A", parentId: 0 }, { id: 2, name: "部门B", parentId: 0 }, { id: 3, name: "部门C", parentId: 1 }, { id: 8, name: "部门H", parentId: 4 }, ]; // 依次去找每个节点下的子节点 // 比如找到 id为2的子节点 可以写成 list.filter((item) => item.parentId === 2); function convert(source, rootId = 0) { return source.filter((rootNode) => { const rs = source.filter((childrenNode) => { return childrenNode.parentId === rootNode.id; }); if (rs.length > 0) rootNode.children = rs; return rootNode.parentId === rootId; }); } ~~~ >[danger] ##### 利用map ~~~ let list = [ { id: 4, name: "部门D", parentId: 1 }, { id: 5, name: "部门E", parentId: 2 }, { id: 6, name: "部门F", parentId: 3 }, { id: 7, name: "部门G", parentId: 2 }, { id: 1, name: "部门A", parentId: 0 }, { id: 2, name: "部门B", parentId: 0 }, { id: 3, name: "部门C", parentId: 1 }, { id: 8, name: "部门H", parentId: 4 }, ]; // 利用key value 形式 // 依次去循环找 到对应父节点,将当前节点插入回去父节点 function convert(source, rootId = 0) { const map = list.reduce((res, v) => ((res[v.id] = v), res), {}); return source.filter((item) => { if (item.parentId in map) { const parentNode = map[item.parentId]; parentNode.children = parentNode.children || []; parentNode.children.push(item); } return item.parentId === rootId; }); } console.log(convert(list)); ~~~ >[info] ## 参考文章 [木易杨前端进阶](https://muyiy.cn/question/program/88.html)