一.前言

在实际开发中,对树形JSON数据处理的业务场景非常常见;而且这些数据必然是多层级的,那么很重要的一点就是要做到递归。特别是在动态路由筛选和树形结构数据筛选中。正所谓,“工欲善其事,必先利其器”。所以本文总结几种用于处理得到我们业务中所需的真正数据的方法。

二.实现方法

  1. splice”方法 (不推荐)
  • 说明:这种方法只适应于唯一性的条件(比如:过滤唯一性id)的场景。
    如果是用在筛选树形数据或者路由菜单(比如:过滤hidden为true)的场景,会因为其实正向删除index值,故导致第一次除外的每次遍历递归的index值不准确,所以删除的值也是不对的,故不推荐

  • 代码实现:

//只适用于唯一性的id的递归过滤
function filterData(arr, id) {
  arr.forEach((item, index) => {
    if (item.id === id) {
      arr.splice(index, 1)
    }
    if (item.children && item.children.length) {
      filterData(item.children, id)
    }
  })
}
  1. 纯“filter”方法 (推荐)
  • 代码实现:
// 递归过滤得到每一项的hidden为false的数据
function filterData2(arr) {
  return arr.filter(item => {
    if (item.children) {
      item.children = filterData2(item.children)
    }
    if (!item.hidden) {
      return true
    }
  })
}
  1. filter”加“map”方法 (推荐)
  • 代码实现:
//深拷贝
function deepCopy(params) {
  // 如果不是对象则退出(可停止递归)
  if (typeof params !== 'object') return;
  // 深拷贝初始值:对象/数组
  let newObj = (params instanceof Array) ? [] : {};
  // 使用 for-in 循环对象属性(包括原型链上的属性)
  for (let i in params) {
    // 只访问对象自身属性
    if (params.hasOwnProperty(i)) {
      // 当前属性还未存在于新对象中时
      if (!(i in newObj)) {
        if (params[i] instanceof Date) {
          // 判断日期类型
          newObj[i] = new Date(params[i].getTime());
        } else if (params[i] instanceof RegExp) {
          // 判断正则类型
          newObj[i] = new RegExp(params[i]);
        } else if ((typeof params[i] === 'object') && params[i].nodeType === 1) {
          // 判断 DOM 元素节点
          let domEle = document.getElementsByTagName(params[i].nodeName)[0];
          newObj[i] = domEle.cloneNode(true);
        } else {
          // 当元素属于对象(排除 Date、RegExp、DOM)类型时递归拷贝
          newObj[i] = (typeof params[i] === 'object') ? deepCopy(params[i]) : params[i];
        }
      }
    }
  }
  return newObj;
}


// 递归过滤得到每一项的hidden为false的数据
function filterData3(arr){
  return arr.filter(item => {
      return !item.hidden
  }).map(i => {
      i = deepCopy(i)
      if (i.children) {
          i.children = filterData3(i.children)
      }
      return i
  })
}

三.文末

感兴趣的童靴可以根据自己项目自行测试和使用。当然,实现的方法还有很多,重要的是掌握其中递归遍历的思想。如大佬们有更有优秀的实现方法,还请多多指教。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐