Tree 树形控件 平铺数据转树状数据

问题

当我们使用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"
    },
   ...
]

页面效果如下

相关推荐
浪裡遊27 分钟前
Nivo图表库全面指南:配置与用法详解
前端·javascript·react.js·node.js·php
罚时大师月色2 小时前
Vue+ts 如何实现父组件和子组件通信
javascript·vue.js·ecmascript
漂流瓶jz2 小时前
快速定位源码问题:SourceMap的生成/使用/文件格式与历史
前端·javascript·前端工程化
samroom2 小时前
iframe实战:跨域通信与安全隔离
前端·安全
fury_1232 小时前
vue3:数组的.includes方法怎么使用
前端·javascript·vue.js
weixin_405023372 小时前
包资源管理器NPM 使用
前端·npm·node.js
宁&沉沦2 小时前
Cursor 科技感的登录页面提示词
前端·javascript·vue.js
Dragonir3 小时前
React+Three.js 实现 Apple 2025 热成像 logo
前端·javascript·html·three.js·页面特效
武天3 小时前
如果使用Vue3.0实现一个 Modal,你会怎么进行设计?
vue.js