JS通过递归,处理树型结构数据

JS通过递归,处理树型结构数据

为什么要将扁平化的数据,变成树型结构?

// 比如这样的数据,后台给的是扁平化数据,前端需要制作成树型结构,供vue-router使用
const routeData = [
		    {
			    id:1,
				pid:0,
				name:'菜单subMenu-1'
			},{
                id:2,
				pid:0,
				name:'菜单subMenu-2'
			},{
			  id:3,
			  pid:1,
			  name:'SBM-1-Menu-1'
			}
		]

先从一个简单的例子开始

现在的数据只有两级:

最终的树型结构是:

       菜单subMenu-1
               SBM-1-Menu-1
               SBM-1-Menu-2
       菜单subMenu-2
               SBM-2-Menu-1
               SBM-2-Menu-2
思路:
   1.
   找到顶级的item元素(pid==0),放到数组parents中。
   找到剩余的item元素(pid!=0),放到数组children中。

   2.
   遍历两个数组。当顶级的id == 子级的pid的时候。给顶级添加children,并把子级push进去。
		const routeData = [
		    {
			    id:1,
				pid:0,
				name:'菜单subMenu-1'
			},{
                id:2,
				pid:0,
				name:'菜单subMenu-2'
			},{
			  id:3,
			  pid:1,
			  name:'SBM-1-Menu-1'
			},{
			  id:4,
			  pid:1,
			  name:'SBM-1-Menu-2'
			},
			{
			  id:5,
			  pid:2,
			  name:'SBM-2-Menu-1'
			},
			{
			  id:6,
			  pid:2,
			  name:'SBM-2-Menu-2'
			}
		]



        
        function ArrayToTree(routeData){
		   // 1 先找出顶级的元素,把顶级元素放数组里面
		   const parents = routeData.filter(item=>{
						return item.pid==0;
						})
		   
		   // 2 把第二级元素组成数组.
		   //然后顶级数组与第二级数组一起遍历。找到顶级的id===子级的pid
		   const children = routeData.filter(item=>{
						return item.pid!=0;
						})
						
		   //console.log(children)
           parents.map(pitem=>{
		       children.map(citem=>{
			       // 子级的pid===顶级的id
			       if(citem.pid==pitem.id){
				      // 没有children就创建一个,有的话就直接push
				      if(pitem.children){
					    pitem.children.push(citem)
					  }else{
					     pitem.children = [citem]
					  }
				   }
			   })
		   })
		   
		   // 使用map,会返回一个新的数组,而不改变原数组
		   //console.log(routeData)
		   //console.log(parents)
		   return parents
		}
		
		ArrayToTree(routeData)



// 这个时候,一个树型结构就出现了。

进入主题:
如果将来菜单的级数特别多怎么办?

       菜单subMenu-1
               SBM-1-Menu-1
                     SBM-1-Menu-1-1
                           SBM-1-Menu-1-1-1
               SBM-1-Menu-2
       菜单subMenu-2
               SBM-2-Menu-1
                    SBM-2-Menu-1-1
               SBM-2-Menu-2
      菜单subMenu-3

这个时候,也是需要 遍历两个数组。当顶级的id == 子级的pid的时候,添加children。也就是说顶级的id == 子级的pid,添加children并push 需要执行多遍,且不知道具体执行多少遍(不知道有几级)的时候,可以用递归

		// 那如果有无限制级子级数据,应该怎么做? -----递归
		const routeData2 = [
		    {
			    id:1,
				pid:0,
				name:'菜单subMenu-1'
			},{
                id:2,
				pid:0,
				name:'菜单subMenu-2'
			},{
			  id:3,
			  pid:1,
			  name:'SBM-1-Menu-1'
			},{
			  id:4,
			  pid:1,
			  name:'SBM-1-Menu-2'
			},
			{
			  id:5,
			  pid:2,
			  name:'SBM-2-Menu-1'
			},
			{
			  id:6,
			  pid:2,
			  name:'SBM-2-Menu-2'
			},{
			  id:7,
			  pid:3,
			  name:'SBM-1-Menu-1-1'
			},{
			  id:8,
			  pid:3,
			  name:'SBM-1-Menu-1-2'
			},{
			  id:9,
			  pid:7,
			  name:'SBM-1-Menu-1-1-1'
			},{
			  id:10,
			  pid:8,
			  name:'SBM-1-Menu-1-2-1'
			}
		]


         // 按照刚才分配两个的思路,递归的话,主要是递归 id==citem.pid
		function ArrayToTree2(routeData){
		    // 1 先找出顶级的元素,把顶级元素放数组里面
		    const parents = routeData.filter((item)=>{
		      return item.pid==0
		   })
		   
		   // 2 把第二级元素组成数组.
		   //然后顶级数组与第二级数组一起遍历。找到顶级的id===子级的pid
		   const children = routeData.filter(item=>{
			  return item.pid!=0;
		   })
		   
		   Findchildren(parents,children)
		}


		function Findchildren(parents,children){						
           parents.map(pitem=>{
		       children.map((citem,index)=>{
			       // 子级的pid===顶级的id
			       if(citem.pid==pitem.id){
				   
				      const myChildren = JSON.parse(JSON.stringify(children))
					  //myChildren.splice(index,1)    优化一下
			          Findchildren([citem],myChildren)
				   
				      // 没有children就创建一个,有的话就直接push
				      if(pitem.children){
					    pitem.children.push(citem)
					  }else{
					     pitem.children = [citem]
					  }
				   }
			   })
		   })
		   console.log(parents)
		}


        ArrayToTree2(routeData2)
 // 在这里,递归可以理解成代码的嵌套,每次遇到 Findchildren ,就把这个给换成代码体里面的内容。也就是当有多级的时候,就会有多层嵌套,比如:
         
        parents.map(pitem=>{
            children.map(citem=>{
                 
                 parents.map(pitem=>{
                      children.map(citem=>{

                           parents.map(pitem=>{
                                children.map(citem=>{

                                   ...里面是函数体的内容,传的参数不一样

                                })
                           })
                        
                      })
                 })
                 
            })
        })
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值