樹結構大家應該都比較熟悉,這里我主要說兩種:一個根節點和多個根節點。一個根節點,就像我們的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:最后提醒一下,數組里面的對象一定是排序過的,也就是說父級一定在前面,它的子級一定在后面。比如:
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丟失。因為它的父級在后面,所以遍歷到它時沒辦法塞給它的父級。謹記:一定要排好序,然后進行數組遍歷
