级联数据取值处理

1,420 阅读2分钟

功能描述

根据后端返回的一个Id,展示对应的name,hover时展示完整层级的name

心路历程

因为是级联数据,层级较多,一层层来回遍历取值消耗性能又麻烦。本着后端处理方便后端弄,前端处理方便前端弄的想法,想让后端加个字段处理好直接返回,前端直接展示(也想着偷懒😹),奈何后端大佬及前端大佬已说好了前端处理🤷‍♀️。

着手处理时,发现级联数据结构也够简单,children里的数据只有name,id字段,parentId也没。让后端同学加上parentId,前端方便处理时,emm。。。,等了半天数据没变。好吧,自己动手,丰衣足食!

  • 返回的级联数据结构:
list:[
  {
    name: 'name1', 
    id: 'id1', 
    children: [
      { 
        name: 'name2', 
        id: 'id2', 
        children: [ 
          { 
            name: 'name3', 
            id: 'id3', 
          }, 
          ... 
        ]
      }, 
      ... 
    ] 
  },
  ...
]

例:根据需求是给一个id3,展示name3,hover name3时浮动展示「name1-name2-name3」。

数据处理

前半部分比较简单,这里不做说明,只处理完整层级的问题。

第一步:首先遍历数据,使用递归的方式,给每层的数据加上parentId,代码如下:

function regroupData(dataList) {
  let newList = [];
  function regroupList(list, parentId) {
    newList = list.map(item => {
      const {
        children,
        id
      } = item;
      if (children && children.length) {
        return {...item,
          parentId,
          children: regroupList(children, id),
        };
      }
      return {...item,
        parentId,
      };
    });
    return newList;
  }
  regroupList(dataList);
  return newList;
}

第二步:可以很方便的取值了

 function queryDataName(list, id) {
    list.forEach(item => {
      const {
        children
      } = item;

      if (item.id === id) {
        names.unshift(item.name);

        // 取其父级的name
        queryDataName(dataList, item.parentId);
      } else if (children && children.length) {
        queryDataName(children, id);
      }
    });

    return names;
  }

  queryDataName(dataList, id);

  return names.join('-');
};

其他方法

解决问题的方式方法多种多样

在我之前,坐在我左手边的大佬同事已做过相同的功能,也看过他的代码。嗯,和我这种方法完全不同。 他的方式是把数据通过遍历改换成一种{id: name}的数据结构。

function queryName(dataList) {...

  let nameMap = {};

  // 这里只把重构数据结构的代码展示出来
  function loopData(list, parent) {
    return list.map(item => {
      const {
        id,
        name,
        children
      } = item;

      const node = (nameMap[id] = {
        parent,
        id,
        name,
      });

      node.children = loopData(children, node);

      return node;
    })
  };

  loopData(dataList);

  ...
}