1 /**
2 * 将数组转化成树结构 array to tree
3 * @param {*} array 数据源
4 * @param {*} options 字段名配置项
5 */
6 function arrayToTree(
7 array = [],
8 options = { id: "id", pid: "pid", children: "children" },
9 ) {
10 let array_ = []; // 创建储存剔除叶子节点后的骨架节点数组
11 let unique = {}; // 创建盒子辅助本轮children合并去重
12 let root_pid = [
13 0,
14 "0",
15 undefined,
16 "undefined",
17 null,
18 "null",
19 "00000000-0000-0000-0000-000000000000"
20 ]; // 可能存在的根节点pid形式
21 array.forEach(item => {
22 // 筛选可以插入当前节点的所有子节点
23 let children_array = array.filter(
24 it => it[options.pid] === item[options.id]
25 );
26 if (item[options.children] && item[options.children] instanceof Array && item[options.children].length > 0) {
27 // 去重合并数组
28 item[options.children].map(i => (unique[i[options.id]] = 1));
29 item[options.children].push(
30 ...children_array.filter(i => unique[i[options.id]] !== 1)
31 );
32 } else {
33 item[options.children] = children_array;
34 }
35 // 当children_array有数据时插入下一轮array_,当无数据时将最后留下来的根节点树形插入数组
36 let has_children = children_array.length > 0;
37 if (
38 has_children ||
39 (!has_children && root_pid.includes(item[options.pid]))
40 ) {
41 array_.push(item);
42 }
43 });
44 // 当数组内仅有根节点时退出,否则继续处理 最终递归深度次。递归深度的解决
45 if (!array_.every(item => root_pid.includes(item[options.pid]))) {
46 return arrayToTree(array_, options);
47 } else {
48 return array_;
49 }
50 }