js实现无限层级树形数据结构(创新算法)

所属分类: 网络编程 / JavaScript 阅读数: 731
收藏 0 赞 0 分享

由于做项目的需要,把一个线性数组转成树形数组,在网上查了很多文章,觉得他们写的太复杂了,于是自己写了一个,在折腾了一下午终于把它写出来啦(激动.gif),用两个filter过滤器就搞定了,代码简洁明了,数据结构小白都能看懂。

js代码:把扁平数据转成树形数据

function setTreeData(source){
  let cloneData = JSON.parse(JSON.stringify(source))   // 对源数据深度克隆
  return cloneData.filter(father=>{           // 循环所有项,并添加children属性
    let branchArr = cloneData.filter(child=> father.id == child.parentId);  // 返回每一项的子级数组
    branchArr.length>0 ? father.children=branchArr : ''  //给父级添加一个children属性,并赋值
    return father.parentId==0;   //返回第一层
  });
}

根据网友给我指出的问题,之前的算法会影响到源数据,之后我对获取的数据进行了深度克隆,完美解决。

封装函数:

function treeData(source, id, parentId, children){  
  let cloneData = JSON.parse(JSON.stringify(source))
  return cloneData.filter(father=>{
    let branchArr = cloneData.filter(child => father[id] == child[parentId]);
    branchArr.length>0 ? father[children] = branchArr : ''
    return father[parentId] == 0    // 如果第一层不是parentId=0,请自行修改
  })
}
 
// 调用时,字段名以字符串的形式传参,如treeData(source, 'id', 'parentId', 'children')

实例1:使用element-ui的组件制作一个树形多级嵌套伸缩菜单栏

实现效果:

vue组件:

<template>
 <el-tree
  :data="treeData"
  :props="defaultProps"
  accordion
  @node-click="handleNodeClick">
 </el-tree>
</template>
 
<script>
  export default {
    name: "Test",
   data(){
    return {
     data : [
      {id:1,parentId:0,name:"一级菜单A",rank:1},
      {id:2,parentId:0,name:"一级菜单B",rank:1},
      {id:3,parentId:0,name:"一级菜单C",rank:1},
      {id:4,parentId:1,name:"二级菜单A-A",rank:2},
      {id:5,parentId:1,name:"二级菜单A-B",rank:2},
      {id:6,parentId:2,name:"二级菜单B-A",rank:2},
      {id:7,parentId:4,name:"三级菜单A-A-A",rank:3},
      {id:8,parentId:7,name:"四级菜单A-A-A-A",rank:4},
      {id:9,parentId:8,name:"五级菜单A-A-A-A-A",rank:5},
      {id:10,parentId:9,name:"六级菜单A-A-A-A-A-A",rank:6},
      {id:11,parentId:10,name:"七级菜单A-A-A-A-A-A-A",rank:7},
      {id:12,parentId:11,name:"八级菜单A-A-A-A-A-A-A-A",rank:8},
      {id:13,parentId:12,name:"九级菜单A-A-A-A-A-A-A-A-A",rank:9},
      {id:14,parentId:13,name:"十级菜单A-A-A-A-A-A-A-A-A-A",rank:10},
     ],
     defaultProps: {
      children: 'children',
      label: 'name'
     }
    }
   },
   computed:{
    treeData(){
     let cloneData = JSON.parse(JSON.stringify(this.data))  // 对源数据深度克隆
     return cloneData.filter(father=>{        
      let branchArr = cloneData.filter(child=>father.id == child.parentId)  //返回每一项的子级数组
      branchArr.length>0 ? father.children = branchArr : ''  //如果存在子级,则给父级添加一个children属性,并赋值
      return father.parentId==0;   //返回第一层
     });
    }
   },
   methods:{
    handleNodeClick(data){
     // console.log(data)
     console.log(this.treeData)
    }
   },
   mounted(){
   }
  }
</script>
 
<style scoped>
 
</style>

Demo

树形数据转成扁平数据,请查看这篇文章:js实现树形数据转成扁平数据

更多精彩内容其他人还在看

js实现图片上传预览原理分析

这篇文章主要为大家详细介绍了js实现图片上传预览的原理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Angular限制input框输入金额(是小数的话只保留两位小数点)

最近做项目遇到这样的需求输入框要求输入金额,只能输入数字,可以是小数,必须保留小数点后两位。下面分为两部分代码给大家介绍实现代码,需要的的朋友参考下吧
收藏 0 赞 0 分享

详解vue-cli + webpack 多页面实例配置优化方法

本篇文章主要介绍了详解vue-cli + webpack 多页面实例配置优化方法,具有一定的参考价值,有兴趣的可以了解一下
收藏 0 赞 0 分享

详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)

本篇文章主要介绍了React-Native解决键盘遮挡问题(Keyboard遮挡问题),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

JavaScript反弹动画效果的实现代码

本文通过实例代码给大家介绍了js反弹动画效果的实现代码,需要的朋友参考下吧
收藏 0 赞 0 分享

解决vue2.x中数据渲染以及vuex缓存的问题

本篇文章主要介绍了vue2.x中请求之前数据显示以及vuex缓存的问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

jsonp跨域请求详解

这篇文章主要为大家详细介绍了jsonp跨域请求的相关资料,激活了所有接口支持浏览器跨域请求的封装,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

解决vue里碰到 $refs 的问题的方法

本篇文章主要介绍了解决vue里碰到 $refs 的问题的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

js自定义弹框插件的封装

这篇文章主要为大家详细介绍了js自定义弹框插件的简单封装,自己封装一个弹框插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

深入理解vue $refs的基本用法

本篇文章主要介绍了深入理解vue $refs的基本用法 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多