Bootstrap

前端数据处理必备技能:数据的树形结构化(递归法与递归法)

在前端的开发过程中,我们有时候会碰到这么种情况,后端给我们的是一组平铺的数据。
而我们需要渲染的却是一个树形结构图,那么我们要怎么将其进行转化呢?

  [
   {id:"01", pid:"",   "name":"老王" },
   {id:"02", pid:"01", "name":"小张" },
   {id:"03", pid:"01",   "name":"老王" },
   {id:"04", pid:"",   "name":"老李" },
   {id:"05", pid:"04", "name":"小黄" },
   {id:"06", pid:"04",   "name":"小丽" }
  ]

从上面的idpid我们可以大致看出来上下级关系,但是数据是一个平铺的数据,并不利于我们进行渲染
这时我们可以封装一个工具,对这个数据进行转化,将其转化成树形结构

一、递归法

递归的方法相对来说比较方便,但对于一部分程序员而言可能不是特别的好理解,下面我拆分进行讲解一下
首先我们先声明一个函数,然后往里面传入两个值

 list // 第一个是你需要进行转化的数组
 pid // 第二个是你需要转化的数据里面的一级数据的值   我们这里pid:''代表的顶级

函数传参使用pid = ''代表你调用函数不进行传值时,这个''就是你的默认值,可以自行进行修改
然后我们先将所有pid=""的数据筛选出来

 function toRee (list,pid = '' ){
   let newList = list.filter(it =>it.pid === pid)
    return newList 
  }

做到这一步,我们得到了有两个pid=''对象的数组
在这里插入图片描述
然后我们对这个数组进行遍历(只要是能循环数组,并且返回这个值的都可以,比如map()等方法都可以),给这两个对象添加一个children属性

并将他的值等于调用的函数的返回值

 function toRee (list,pid = '' ){
   let newList= list.filter(it =>it.pid === pid)
    newList.forEach(it => it.children = toRee(list,it.id) )
    return newList 
  }

这个返回值是关键.他是一个数组,并且是一个pid等于newList里面每一个对象id的值
这样就形成了一个递归,直到没有newList不再是数组就开始进行返回
在这里插入图片描述

相对于下面的非递归相比,越是层级深的数据使用递归函数,他的循环次数会越多

二、非递归法

这里我写的是一种非递归法进行的数据转化

function totree(arr) {
  const newArr = []
  const map = {}

先进行变量的声明

 arr.forEach(item => {
   if(!item.children) item.children = [];  判断数据是否有子级   没有则进行子级的添加
   map[item.id] = item   // 添加对应的映射关系 
 })

再通过循环 判断每一个数据是否有子级 没有就添加子级属性,值是一个空数组

重点 这里进行了数据的映射

将所有的数据的id去出来,然后采用键值对的形式生成一个新的对象,方便我们后面进行比对

{
 01: {id:"01", pid:"",   "name":"老王" },
 02: {id:"02", pid:"01", "name":"小张" },
 03: {id:"03", pid:"01",   "name":"老王" },
 04: {id:"04", pid:"",   "name":"老李" },
 05: {id:"05", pid:"04", "name":"小黄" },
 06: {id:"06", pid:"05",   "name":"小丽" }
  }

最后再进行一次循环,将所有有pid值的数据添加到跟pid对应的id映射的对象的子级里面

 arr.forEach(item => {
   if (map[item.pid]) {
     map[item.pid].children.push(item)
   } else {
     newArr.push(item)
   }
 })
 return newArr
}
export default totree

这样就完成了所有的操作,将newArr进行return就行

判断上下级的数据不同的话,修改里面的对应数据即可
完整代码如下

function totree(arr) {
  const newArr = []
  const map = {}
  arr.forEach(item => {
    if(!item.children) item.children = [];  判断数据是否有子级   没有则进行子级的添加
    map[item.id] = item // 添加对应的映射关系
  })
  arr.forEach(item => {
    if (map[item.pid]) {
      map[item.pid].children.push(item)
    } else {
      newArr.push(item)
    }
  })
  return newArr
}
export default totree

最后欢迎大家点赞

;