这篇就是写一下平级结构与树形结构之间的转化,之前也有写过类似的:
对象数组转为树形结构
js树形结构,根据里层id找出它所属的每层父级集合
大家有兴趣可以去看一下,也算是简单巩固一下js吧
1. 对象数组转为树形结构
① 常见格式
一般如果平级的数组结构可以转化为树形,都会有id和parentId两个字段来标识子级和父级,来确定关系
测试数据
let source = [
{
title: '角色编辑',
parentId: 22,
id: 222,
},
{
title: '系统管理',
parentId: 0,
id: 1,
},
{
title: '角色新增',
parentId: 22,
id: 221,
},
{
title: '角色删除',
parentId: 22,
id: 223,
},
{
title: '用户新增',
parentId: 33,
id: 331,
},
{
title: '菜单新增',
parentId: 11,
id: 111,
},
{
title: '菜单编辑',
parentId: 11,
id: 112,
},
{
title: '用户管理',
parentId: 0,
id: 33,
},
{
title: '菜单管理',
parentId: 1,
id: 11,
},
{
title: '菜单删除',
parentId: 11,
id: 113,
},
{
title: '用户编辑',
parentId: 33,
id: 332,
},
{
title: '角色管理',
parentId: 1,
id: 22,
},
{
title: '用户删除',
parentId: 33,
id: 333,
}
]
方法:
function toTree(list, id = 'id', pid = 'parentId', childrenKey = 'children') {
const target = []
const map = {}
list.forEach(item => {
map[item[id]] = item
})
list.forEach(item => {
let parent = map[item[pid]]
if (parent) {
(parent[childrenKey] || (parent[childrenKey] = [])).push(item)
} else {
target.push(item)
}
})
return target
}
② 不常见格式
这种也是平级结构,但是给你的全部是叶子节点,每条数据里面都包含了他上级的id和name,一般这种都会确定有几级
就想下面这个测试数据就是,返回了所有的人员信息,每条人员数据里面都包含了他所属的单位(一级)的id(unitId)和name(unitName)、以及他所属的部门(二级)的id (deptId)和name(deptName)。然后将其构建出一个树形数据来
测试数据
let data = [
{
imageUrl: 'c://image/1.jpg',
employeeId: '100000',
employeeName: '张三',
employeeGender: 0,
deptId: 0,
deptName: '软件',
unitId: 0,
unitName: '山东分院',
phoneNum: '18366666666',
accountBalance: null,
email: '1@cmdi.com',
isOwn: 0,
employeeStatus: 0,
queryString: null,
},
{
imageUrl: 'c://image/1.jpg',
employeeId: '100001',
employeeName: '小王',
employeeGender: 0,
deptId: 1,
deptName: '测试',
unitId: 0,
unitName: '山东分院',
phoneNum: '18366666666',
accountBalance: null,
email: '1223145@cmdi.com',
isOwn: 0,
employeeStatus: 0,
queryString: null,
},
{
imageUrl: 'c://image/1.jpg',
employeeId: '100002',
employeeName: '李四',
employeeGender: 0,
deptId: 2,
deptName: '测试',
unitId: 1,
unitName: '信通子公司',
phoneNum: '18366666666',
accountBalance: null,
email: '3123145@cmdi.com',
isOwn: 0,
employeeStatus: 0,
queryString: null,
},
{
imageUrl: 'c://image/1.jpg',
employeeId: '100003',
employeeName: '小李',
employeeGender: 0,
deptId: 3,
deptName: '开发',
unitId: 1,
unitName: '信通子公司',
phoneNum: '18366666666',
accountBalance: null,
email: '1234145@cmdi.com',
isOwn: 0,
employeeStatus: 0,
queryString: null,
},
{
imageUrl: 'c://image/1.jpg',
employeeId: '100004',
employeeName: '王五',
employeeGender: 0,
deptId: 1,
deptName: '测试',
unitId: 0,
unitName: '山东分院',
phoneNum: '18366666666',
accountBalance: null,
email: '1231545@cmdi.com',
isOwn: 0,
employeeStatus: 0,
queryString: null,
},
]
方法:
function useUnitDeptEmpTree(emps) {
const tree = []
for (let emp of emps) {
if (!emp.id) {
emp.id = getUuid()
}
emp.name = emp.employeeName
let unit = tree.find(item => item.id == emp.unitId)
if(!unit) {
unit = { id: emp.unitId, name: emp.unitName, children: [] }
tree.push(unit)
}
let dept = unit.children.find(item => item.id == emp.deptId)
if(!dept) {
dept = { id: emp.deptId, name: emp.deptName, children: [] }
unit.children.push(dept)
}
dept.children.push(emp)
}
return tree
}
function getUuid() {
const temp_url = URL.createObjectURL(new Blob())
const uuid = temp_url.toString()
URL.revokeObjectURL(temp_url) //释放这个url
return uuid.substring(uuid.lastIndexOf('/') + 1)
}
2. 遍历树形结构、扁平树形
就是我们现在有个树形结构,如何遍历到整个树形的每一项呢,也同样的肯定会有个标识子节点的属性,例如:children,然后我们可以通过递归和forEach方法即可遍历整个树形,为了更方便起见,我们可以传递一个callback回调函数,这样遍历到每个节点的时候可以更方便的写一些自己的逻辑,就像forEach似的,工具函数如下:
测试数据
let tree = [
{
"title": "系统管理",
"parentId": 0,
"id": 1,
"children": [
{
"title": "菜单管理",
"parentId": 1,
"id": 11,
"children": [
{
"title": "菜单新增",
"parentId": 11,
"id": 111
},
{
"title": "菜单编辑",
"parentId": 11,
"id": 112
},
{
"title": "菜单删除",
"parentId": 11,
"id": 113
}
]
},
{
"title": "角色管理",
"parentId": 1,
"id": 22,
"children": [
{
"title": "角色编辑",
"parentId": 22,
"id": 222
},
{
"title": "角色新增",
"parentId": 22,
"id": 221
},
{
"title": "角色删除",
"parentId": 22,
"id": 223
}
]
}
]
},
{
"title": "用户管理",
"parentId": 0,
"id": 33,
"children": [
{
"title": "用户新增",
"parentId": 33,
"id": 331
},
{
"title": "用户编辑",
"parentId": 33,
"id": 332
},
{
"title": "用户删除",
"parentId": 33,
"id": 333
}
]
}
]
方法:
function mapTree(treeData, callback, childrenKey = 'children', level = 0) {
treeData.forEach(item => {
const curItem = JSON.parse(JSON.stringify(item))
curItem.level = level
callback(curItem, treeData)
if(item?.[childrenKey]?.length) {
mapTree(item[childrenKey], callback, childrenKey, level + 1)
}
})
}
这里举个例子:就是我们想扁平整个树形,就可以使用上面的工具方法
let list = []
mapTree(tree, item => {
if(item.children) delete item.children
list.push(item)
})
console.log(list)