当前位置: 首页 > news >正文

element-plus树形数据与懒加载的实现

环境

vue版本: 2.6.14

需求

树形表格,默认返回当前登录人拥有权限的一个层级的数据,通过点击load懒加载获取下一层的数据,要求有新增、编辑、删除操作。

树类型的懒加载:

当row中包含children字段时,被视为树形数据。渲染嵌套数据需要prop的row-key。且子节点数据可以异步加载。通过row中的hasChildren字段来指定哪些行是包含子节点。children与hasChildren都可以通过tree-props进行配置。需要设置el-table的lazy属性为true且需要load加载函数,数据懒加载且不可使用 default-expand-all 属性。

代码实现如下:

   <el-table
      ref="tableRef"
      :loading="loading"
      :data="tableData"
      row-key="id"
      border
      lazy
      :load="load"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
    >
      <el-table-column prop="date" label="Date" />
      <el-table-column prop="name" label="Name" />
      <el-table-column prop="address" label="Address" />
      <el-talbe-column label="操作">
        <template v-slot="{ row }">
          <el-button type="primary" @click="() => add(row.id)">添加</el-button>
          <el-button type="default" @click="() => edit(row.id)">编辑</el-button>
          <el-button type="danger" @click="() => delete(row.parentId)">删除</el-button>
        </template>
      </el-talbe-column>
    </el-table>
export default {
  data() {
    return {
      tableData: [],
      loading: false,
      loadMap: new Map()
    }
  },
  async mounted() {
    this.queryTableList();
  },
  methods:{
    async queryTableList() {
      this.loading = true;
      // 接口调用获取树形数据
      try {
          const { data, code } = await api.getList({id: undefined});
          if(code === 200) {
            // 将返回的数据结构处理为树形结构
            this.tableData = this.processTreeData(data);
            return this.tableData;
          } else {
            return []
          }
      } finally {
        this.loading = false;
      }
    },
    processTreeData(data) {
      return data.map(item => {
        // 添加hasChildren属性,表示是否有子节点
        const hasChildren = item.children && item.children.length > 0;

        // 递归处理子节点
        const children = hasChildren ? this.processTreeData(item.children) : [];
        // 假如每个节点的类型都是不同的,最后一个子节点的type为last
        return {
          ...item,
          hasChildren: item.type === 'last' ? hasChildren : !hasChildren,
          children
        }
      })
    },
    async load(tree, treeNode, resolve) {
      this.loading = true;
      this.loadMap.set(tree.id, { tree, treeNode, resolve});
      try {
          const { data, code } = await api.getList({id: tree.id});
          if(code === 200) {
             if(data && data.length) {
               resolve(this.processTreeData(data))
             } else {
                this.$set(this.$refs.tableRef.store.states.lazyTreeNodeMap, tree.id, [])
                 resolve([])
             }
          } else {
             resolve([])
          }
      } finally {
        this.loading = false;
      }
    },
    // 刷新列表
    refresh(id) {
      if(this.loadMap.get(id)) {
        const { tree, treeMap, resolve } = this.loadMap.get(id);
        if(tree) {
          this.load(tree, treeMap, resolve)
        }
      }
    },
    // 添加节点
    add(id) {
      // 添加成功后,直接调用
      this.refresh(id);
    },
    // 编辑节点
    edit(id) {
      // 根据当前id获取该条数据信息,返回数据中要求有父级的id
      const parentId = 111; // 父级返回的id
      this.refresh(parentId);
    },
    // 删除
    delete(id) {
      // 需要传递父级的id
      this.refresh(id);
    }
  }
}

一、要求最后一个子节点不显示要展开的箭头

item.type === 'last' ? hasChildren : !hasChildren

二、当返回的数据为空数组,会导致列表一直显示加载状态。

this.$set(this.$refs.tableRef.store.states.lazyTreeNodeMap, tree.id, [])

清空 lazyTreeNodeMap 中的对应数据:在数据为空数组时,手动清空 lazyTreeNodeMap 中对应的数据,这样可以避免加载状态的持续显示。

这个问题的主要原因在于懒加载的机制:懒加载的load函数只在第一次打开子节点时触发,之后不会再次触发,因此数据无法实时刷新。


扩展:将一个子节点迁移至另一个父节点下面

避免遇到的问题:

[Vue warn]: Duplicate keys detected: '111'. This may cause an update error.

引起该问题的原因是列表中数据id值重复。

*在迁移数据时,一定要先调用被迁移子节点的父节点,再调用新的父节点获取数据,避免数据冲突。

欢迎在评论区讨论,完善功能代码。

相关文章:

  • kettle从入门到精通 第九十二课 ETL之kettle 使用Kettle的Carte对外发布读写接口
  • 设计模式教程:命令模式(Command Pattern)
  • .NET版PDF处理控件Aspose.PDF教程:在 C# 中将 TIFF 文件转换为 PDF
  • hive迁移补数脚本细粒度 表名-分区唯一键
  • C语言基础系列【15】union 共用体
  • Apache Doris 实现毫秒级查询响应
  • 【RabbitMQ业务幂等设计】RabbitMQ消息是幂等的吗?
  • Ubuntu安装PostgreSQL
  • 城市地质安全专题连载⑦ | 加强国土空间规划管控,规避城市地质安全风险
  • 跟着李沐老师学习深度学习(十二)
  • javaSE学习笔记21-线程(thread)-锁(synchronized 与Lock)
  • 从零开始用STM32驱动DRV8301:无人机/机器人电机控制指南
  • 基于图扑 HT 可视化实现智慧地下采矿可视化
  • CentOS更换yum源
  • 安装MySQL9.1.0-winx64.msi的报错解决办法:Database initialization failed。(也适用9.2.0)
  • 基于spring的策略模式
  • 【树莓派Pico设备驱动】-MAX7219驱动8位7段数码管(基于SPI)
  • 微信小程序地图map全方位解析
  • Vue实战【后端返回ArrayBuffer时,前端如何处理并成功下载ArrayBuffer文件】
  • Hive JOIN过滤条件位置玄学:ON vs WHERE的量子纠缠
  • 网站建设设计报价/网推团队
  • 网站首页流程图/优化关键词排名提升
  • wordpress模板排行榜/性能优化工具
  • 网站建设 微信营销/网站优化排名易下拉系统
  • 好玩的网站源码/公司百度推广一年多少钱
  • 自己怎样给网站做推广/营销方法有哪几种