菜单平铺数据构建树状结构
关于多级数列的联级显示需要的是树状结构例如:
[
{
id: 1,
father_id: 0,
status: 1,
name: '生命科学竞赛',
_child: [
{
id: 2,
father_id: 1,
status: 1,
name: '野外实习类',
_child: [
{ id: 3, father_id: 2, status: 1, name: '植物学' },
{ id: 4, father_id: 2, status: 1, name: '动物学' },
{ id: 5, father_id: 2, status: 1, name: '微生物学' },
{ id: 6, father_id: 2, status: 1, name: '生态学' }
]
},
{
id: 7,
father_id: 1,
status: 1,
name: '科学研究类',
_child: [
{ id: 8, father_id: 7, status: 1, name: '植物学与植物生理学' },
{ id: 9, father_id: 7, status: 1, name: '动物学与动物生理学' },
{ id: 10, father_id: 7, status: 1, name: '微生物学' },
{ id: 11, father_id: 7, status: 1, name: '生态学' },
{
id: 21,
father_id: 7,
status: 1,
name: '农学',
_child: [
{ id: 22, father_id: 21, status: 1, name: '植物生产类' },
{ id: 23, father_id: 21, status: 1, name: '动物生产类' },
{ id: 24, father_id: 21, status: 1, name: '动物医学类' }
]
},
{
id: 41,
father_id: 7,
status: 1,
name: '药学'
},
{ id: 55, father_id: 7, status: 1, name: '其他' }
]
},
{ id: 71, father_id: 1, status: 1, name: '添加' }
]
}
]
但实际情况在数据库便于存储经常直接取出的结果类似于如下:
[
{ id: 1, father_id: 0, status: 1, name: '生命科学竞赛' },
{ id: 2, father_id: 1, status: 1, name: '野外实习类' },
{ id: 3, father_id: 2, status: 1, name: '植物学' },
{ id: 4, father_id: 2, status: 1, name: '动物学' },
{ id: 5, father_id: 2, status: 1, name: '微生物学' },
{ id: 6, father_id: 2, status: 1, name: '生态学' },
{ id: 7, father_id: 1, status: 1, name: '科学研究类' },
{ id: 8, father_id: 7, status: 1, name: '植物学与植物生理学' },
{ id: 9, father_id: 7, status: 1, name: '动物学与动物生理学' },
{ id: 10, father_id: 7, status: 1, name: '微生物学' },
{ id: 11, father_id: 7, status: 1, name: '生态学' },
{ id: 21, father_id: 7, status: 1, name: '农学' },
{ id: 22, father_id: 21, status: 1, name: '植物生产类' },
{ id: 23, father_id: 21, status: 1, name: '动物生产类' },
{ id: 24, father_id: 21, status: 1, name: '动物医学类' },
{ id: 41, father_id: 7, status: 1, name: '药学' },
{ id: 55, father_id: 7, status: 1, name: '其他' },
{ id: 71, father_id: 1, status: 1, name: '添加' },
{ id: 56, father_id: 0, status: 1, name: '考研相关' },
{ id: 57, father_id: 56, status: 1, name: '政治' },
{ id: 58, father_id: 56, status: 1, name: '外国语' },
{ id: 65, father_id: 0, status: 1, name: '找工作' },
{ id: 66, father_id: 65, status: 1, name: '招聘会' },
{ id: 67, father_id: 65, status: 1, name: '简历' },
{ id: 70, father_id: 0, status: 1, name: '其他' },
{ id: 72, father_id: 70, status: 1, name: '新增的根级12311111' }
]
包含自身id和上层级关于的father_id,此时这种结构要想正常使用到前端,则需要转化为前面提到的树状结构。 构建代码如下,在一次遍历数组后得到结果。
代码思路如下
1.将所有id存储在idMap中利用自身id管理;将还没遍历父节点的子节点暂存到tempMap中利用father_id管理;
2.判断当前节点父子节点归属,tempMap[id]判断是否存在以当前节点为父节点的暂存子节点集合;若有则拼接到当前节点_child上
3.利用fatherId是否为0或空 判断是否为最高层级节点,若为最高层级则利用result统一指向他们;若不为最高层级,即存在父节点;
4.对接当前节点父级,遍历到当前节点时利用idMap[fatherId] 查看其父节点是否已遍历完,若遍历完则拿到父节点并将自身放入父节点的_child中,若父节点还没遍历则利用fatherId暂存tempMap中。
buildMenuData (data) {
const result = []
const idMap = {}
const tempMap = {}
let i = data.length
while (i--) {
const fatherId = data[i].father_id
const id = data[i].id
idMap[id] = data[i]
if (tempMap[id]) { // 承接子级
if (data[i]._child) data[i]._child = data[i]._child.concat(tempMap[id])
else data[i]._child = tempMap[id]
delete tempMap[id]
data[i]._child.sort((a, b) => a.id - b.id)
}
if (fatherId) {
if (idMap[fatherId]) { // 对接父级
if (idMap[fatherId]._child) idMap[fatherId]._child.push(data[i])
else idMap[fatherId]._child = [data[i]]
idMap[fatherId]._child.sort((a, b) => a.id - b.id)
} else { // 找不到父级时的暂存
if (tempMap[fatherId]) tempMap[fatherId].push(data[i])
else tempMap[fatherId] = [data[i]]
}
} else {
result.push(data[i])
}
}
result.sort((a, b) => a.id - b.id)
return result
}