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 }