树结构你们应该都比较熟悉,这里我主要说两种:一个根节点和多个根节点。
一个根节点,就像咱们的html节点,不可能有和它同级的;多个根节点,好比咱们的一二级导航栏。
下面一个个分析:html
let arr = [ { menuId: 1, name: '系统1', parentMenu: null }, { menuId: 2, name: '系统1_0', parentMenu: 1 }, { menuId: 3, name: '系统1_1', parentMenu: 1 } ] function turnToTreeOfOneRoot(arr) { if (!Array.isArray(arr)) { throw new Error('is not array') } else { return arr.reduce((cur, item) => { if (item.parentMenu == null) { cur = { children: [], ...item } } else if (item.parentMenu == cur.menuId) { cur.children.push(item) } return cur }, {}) } } turnToTreeOfOneRoot(arr)
var arr1 = [ { menuId: 1, name: '系统管理1', parentMenu: null }, { menuId: 2, name: '系统管理1_0', parentMenu: 1 }, { menuId: 3, name: '系统管理1_1', parentMenu: 1 }, { menuId: 4, name: '系统管理2_0', parentMenu: 2 } ] function turnToTreeOfOneRootPlus(arr) { var obj = {} arr.forEach(item => { if (item.parentMenu == null) { obj = item } }) return arr.reduce((h, m) => { // 若是不是根节点 if (m.parentMenu) { foo(h, m) } // 在obj里面为cur找到归宿 function foo(obj, cur) { if (obj.menuId === cur.parentMenu) { if (!obj.children) { obj.children = [] } obj.children.push(cur) } else if (obj.children) { obj.children.forEach(item => { foo(item, cur) }) } } return h }, obj) } turnToTreeOfOneRootPlus(arr1)
let arr2 = [ { menuId: 1, name: '系统1', parentMenu: null }, { menuId: 2, name: '系统1_0', parentMenu: 1 }, { menuId: 3, name: '系统1_1', parentMenu: 1 }, { menuId: 4, name: '系统2', parentMenu: null }, { menuId: 5, name: '系统4_0', parentMenu: 4 } ] function turnToTreeOfManyRoot(arr) { if (!Array.isArray(arr)) { throw new Error('is not array') } else { var roots = [] arr.forEach(item => { if (item.parentMenu == null) { item.children = [] roots.push(item) } }) return arr.reduce((roots, cur) => { roots.forEach(item => { // 若是是根节点 if (item.menuId == cur.parentMenu) { item.children.push(cur) } }) return roots }, roots) } } turnToTreeOfManyRoot(arr2)
var arr3 = [ { menuId: 1, name: '系统管理1', parentMenu: null }, { menuId: 2, name: '系统管理2', parentMenu: null }, { menuId: 3, name: '系统管理1_0', parentMenu: 1 }, { menuId: 4, name: '系统管理1_1', parentMenu: 1 }, { menuId: 5, name: '系统管理2_0', parentMenu: 2 }, { menuId: 6, name: '系统管理5_0', parentMenu: 5 }, { menuId: 7, name: '系统管理3', parentMenu: null } ] function turnToTreeOfManyRootPlus(arr) { var arrs = [] arr.forEach(item => { if (!item.parentMenu) { arrs.push(item) } }) return arr.reduce((h, m) => { if (m.parentMenu) { foo(h, m) } function foo(arr, cur) { arr.forEach(item => { if (item.menuId === cur.parentMenu) { if (!item.children) { item.children = [] } item.children.push(cur) } else if (item.children) { foo(item.children, cur) } }) } return h }, arrs) } turnToTreeOfManyRootPlus(arr3)
ps:最后提醒一下,数组里面的对象必定是排序过的,也就是说父级必定在前面,它的子级必定在后面。好比:json
let arr = [ { menuId: 1, name: '系统1', parentMenu: null }, { menuId: 4, name: '系统2_0', parentMenu: 2 }, { menuId: 2, name: '系统1_0', parentMenu: 1 }, { menuId: 3, name: '系统1_1', parentMenu: 1 } ]
这样的数组,会致使menuId: 4
丢失。由于它的父级在后面,因此遍历到它时没办法塞给它的父级。谨记:必定要排好序,而后进行数组遍历数组