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

页面效果如下

相关推荐
智能化咨询12 分钟前
【Linux】【实战向】Linux 进程替换避坑指南:从理解 bash 阻塞等待,到亲手实现能执行 ls/cd 的 Shell
前端·chrome
Anson Jiang14 分钟前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件
掘金安东尼17 分钟前
黑客劫持:周下载量超20+亿的NPM包被攻击
前端·javascript·面试
剑亦未配妥1 小时前
移动端触摸事件与鼠标事件的触发机制详解
前端·javascript
人工智能训练师7 小时前
Ubuntu22.04如何安装新版本的Node.js和npm
linux·运维·前端·人工智能·ubuntu·npm·node.js
Seveny077 小时前
pnpm相对于npm,yarn的优势
前端·npm·node.js
yddddddy8 小时前
css的基本知识
前端·css
昔人'8 小时前
css `lh`单位
前端·css
Nan_Shu_61410 小时前
Web前端面试题(2)
前端
知识分享小能手10 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue