问题
当我们使用element-ui的树形组件的时候,我们发现组件需要data里的数据是一种层层嵌套的树状结构
但是一般发送请求后服务器返回的数据是平铺数据
平铺数据是一种线性结构,所有的数据都存储在一个平等的层次中,没有明显的层级关系。
示例数据如下
javascript
[
{
"id": 1,
"name": "组织架构",
"description": "组织架构",
"type": 1,
"code": "department",
"pid": 0,
"enVisible": "1",
},
{
"id": 2,
"name": "角色管理",
"description": "角色管理菜单",
"type": 1,
"code": "role",
"pid": 0,
"enVisible": "1"
},
...
{
"id": 1606,
"name": "子权限",
"description": "123123",
"type": 2,
"code": "123",
"pid": 1,
"enVisible": "1"
}
]
我们要将平铺数据转换为树状数据
树状数据是一种分层结构,数据以层级关系的形式组织,每个节点可以包含一个或多个子节点。
这个时候我们可以利用函数将平铺数据转换为树状数据,从而达到组件的数据要求
在上面的示例中,数据的父子关系通过唯一的 id 字段和其他对象中的 pid 字段的对应来进行识别。具体而言,当一个对象的 id 值等于另一个对象的 pid 值时,这两个对象就存在父子关系。
例如:一个对象的id为1,另一个对象pid为1,那么前者就是后者的父亲,需要将后者加到前者对象中
解决方法
以Vue为例,这个时候我们可以去utils工具箱文件夹中创建一个工具例如transformListToTree的方法来进行转换
javascript
// 转树形结构的递归函数
export function transformListToTree(arr, id) {
// 存储树状结构的数组
const list = [];
// 遍历平铺的数据数组
arr.forEach((item) => {
// 如果当前元素的父级标识符(pid)等于传入的父级标识符(id)
if (item.pid === id) {
// 递归调用函数,查找当前元素的子节点
const tmp = transformListToTree(arr, item.id);
// 如果当前元素有子节点,将子节点赋值给当前元素的 children 属性
if (tmp.length > 0) {
item.children = tmp;
}
// 将当前元素添加到存储树状结构的数组中
list.push(item);
}
});
// 返回存储树状结构的数组
return list;
}
如何使用
在组件中使用transformListToTree方法
javascript
<template>
<el-tree
ref="treeRef"
:data="permisstionList"
:props="defaultProps"
show-checkbox
default-expand-all
:expand-on-click-node="false"
check-strictly
node-key="id"
/>
</template>
<script>
import { transformListTree } from '@/utils/transform';
export default {
data() {
return {
// 平铺数据
flatData: [
// ... 平铺数据数组
],
// 转换后的树状数据
permisstionList: [],
// Element UI 树形组件的 props 配置
defaultProps: {
// ... 具体配置项
children: 'children', // 子节点属性名
label: 'name' // 节点文本属性名
},
};
},
created() {
// 在组件创建时进行数据转换
this.permisstionList = transformListToTree(this.flatData, 0)
},
};
</script>
最终结果
转换后的数据
javascript
[
{
"id": 1,
"name": "组织架构",
"description": "组织架构",
"type": 1,
"code": "department",
"pid": 0,
"enVisible": "1",
"children": [
{
"id": 1606,
"name": "子权限",
"description": "123123",
"type": 2,
"code": "123",
"pid": 1,
"enVisible": "1"
}
]
},
{
"id": 2,
"name": "角色管理",
"description": "角色管理菜单",
"type": 1,
"code": "role",
"pid": 0,
"enVisible": "1"
},
...
]
页面效果如下