数组转树形结构

395 阅读3分钟

数组转树形的用途 为什么面试的时候会问关于它呢,其实这种树形结构的数据在项目中还是很常见的。树形结构的数据的主要用途就是供菜单渲染使用。不过这种数据的返回一般是由后端人员完成的,也不排除由前端人员转换的情况。

前端转换的场景:当我们拿到用户角色对应的菜单权限数组时,像:[home,goods,goodsmanage,chart,line] ,还拿到了整个菜单的数组列表,我们需要根据用户的权限来动态渲染出对应的菜单,此时我们应该如何处理呢?

1.根据整个菜单的数组列表和权限数组,生成该用户对应的菜单列表

2.把菜单列表转化为树形结构对象

3.根据树形结构对象渲染对应的菜单

数组转树形 现有后台返回的用户信息和完整菜单数组数据如下: 完整菜单数组

const list=[
{id:"0",pid:"",title:"菜单",key:'menu'},
{id:"1",pid:"0",title:"首页",key:'home'},
{id:"2",pid:"0",title:"商品",key:'goods'},
{id:"2-1",pid:"2",title:'商品管理',key:'goodsmanage'},
{id:"2-2",pid:'2',title:'商品分类',key:'goodscategory'},
{id:"3",pid:"0",title:"图表管理",key:'chart'},
{id:"3-1",pid:'3',title:"饼图",key:'pie'},
{id:"3-2",pid:'3',title:"条形图",key:'bar'},
{id:"3-3",pid:'3',title:"折线图",key:'line'}
]

用户信息

const user={
    name:'xxx',
    role:'xx'
    auth:['home','goods','goodsmanage','goodscategory','chart','pie']
}

1.先找到该角色对应的菜单列表

const myList=[]     // 定义该用户对应的菜单列表

for(let i of list)
{
    // 如果找到用户对应的菜单项,把该菜单项加进去
    if(user.auth.indexOf(i.key)!==-1)   myList.push(i)
}

2.开始转树形 方法一:非递归思路 把所有孩子收纳到各自麾下,然后只需找到根节点即可。因为根节点会收纳自己的孩子,根节点的孩子也会收纳自己的孩子,以此类推。因此我们只需要找到根节点就相当于找到整颗树形了。

function createTree(arr=[]){
	let res
	for(let i of arr){
		for(let j of arr){
			if(!i.pid) res=i    // 找到根节点
			if(i.id==j.pid)     // 让每个节点都去去寻找自己的子节点,然后将子节点收入其中
			{
			  if(!i.children)i.children=[]
			  i.children.push(j)
			}  
		}
	}
	return res
}
const myTree=createTree(myList)
console.log(myTree)

方法二:递归思路 先找到根节点,然后把根节点的直接孩子收入自己麾下,收入的孩子是递归后的孩子。(递归后的孩子会找到自己的孩子)

function createTree(arr=[],id){
	let res={}
	for(let i of arr){   
		if(id==i.id) {    // 先找到跟节点 
		  res.title=i.title
		}
		
		if(id==i.pid){   // 把根节点的直接子节点递归收入其中      
			if(!res.children) res.children=[]
			res.children.push(createTree(arr,i.id))
		}
	}
	return res
}
const myTree=createTree(list,"0")   // 0是根节点的id
console.log(myTree)

3.渲染菜单,以antd的Menu组件为例。

import {PureComponent} from "react"
import {Menu} from 'antd'

class index extends PureComponent{

	
linkto=(i)=>{
this.props.history.push(`${this.props.match.path}/${i.keyPath.reverse().join('/')}`)
}
	
render() {
	
	return (
	<div className='leftnav'>
	<Menu
	defaultSelectedKeys={keys}
	defaultOpenKeys={keys}
	mode="inline"
	theme="dark"
	items={this.state.myTree.children}    {/*这里的myTree就是上面的树形数据*/
	onClick={this.linkto}
	/>
	
	</div>
	)
	}
}
export default index

树形转数组

其实树形结构转数组涉及到了数据结构关于树的算法,例:先序遍历、中序遍历、后序遍历、层序遍历,区别就在于节点输出的顺序不一致。如果想了解关于树的这些算法,可以看看我发布的一篇文章——>js实现树的前、中、后、层序遍历。

function treeToList(obj={}){
	const res=[]
  function a(obj={}){
	res.push({id:obj.id,pid:obj.pid})
	if(obj.children){
		for(let v of obj.children){
		 a(v)
		}
	}
	}
	a(obj)
	return res
}
const list=treeToList(myTree)
console.log(list)

原文链接:blog.csdn.net/qq_61233877…