菜单数据层级构建

294 阅读3分钟

菜单平铺数据构建树状结构

关于多级数列的联级显示需要的是树状结构例如:

[
  {
    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
  }