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"
    },
   ...
]

页面效果如下

相关推荐
小雨青年18 分钟前
MateChat 进阶实战:打造零后端、隐私安全的“端侧记忆”智能体
前端·华为·ai·华为云·状态模式
勇气要爆发31 分钟前
问:ES5和ES6的区别
前端·ecmascript·es6
永不停歇的蜗牛1 小时前
Maven的POM文件相关标签作用
服务器·前端·maven
芳草萋萋鹦鹉洲哦1 小时前
【vue/js】文字超长悬停显示的几种方式
前端·javascript·vue.js
HIT_Weston2 小时前
47、【Ubuntu】【Gitlab】拉出内网 Web 服务:Nginx 事件驱动分析(一)
前端·ubuntu·gitlab
开发者小天2 小时前
React中的 闭包陷阱
前端·javascript·react.js
翔云 OCR API2 小时前
承兑汇票识别接口技术解析-开发者接口
开发语言·前端·数据库·人工智能·ocr
涔溪2 小时前
Vue3 的核心语法
前端·vue.js·typescript
G***E3163 小时前
前端在移动端中的React Native Web
前端·react native·react.js
云烟飘渺o3 小时前
JPA 的脏检查:一次“没 save() 却更新了”的排查记录
前端