element实现需同时满足多行合并和展开的表格

news2025/2/25 12:09:22

element实现需同时满足多行合并和展开的表格

需求描述:

以下面这张图为例,此表格的“一级表格”这一行可能存在多行数据,这种情况下需要将“一级指标”,“一级指标扣分xxx”,“一级指标关联xxx”这三列数据的行展示根据后面数据(“二级指标”,…等)进行合并。同时,对于含有多条“二级指标”的单行数据,需要支持可展开可合并。

image-20250224154117587

image-20250224154222445

技术选择:

当前项目的技术栈是vue3,虽然公司有自己组件库,但是私有库有不完美的地方,而且暴露出来的api不够详细,所以选择了element-plus。

element有案例提供“合并行或列”和“展开行的表格”,但是没有提供两者混合使用的表格,本文章以此为基础进行开发。

image-20250224155604294

image-20250224155642052

技术实现:

1. span-method

这是el-table中提供的合并行或列的计算方法以本段代码中提供的objectSpanMethod为例:

  1. 判断是否为子行

    • const isChildRow = row.first === "";:通过检查 row.first 是否为空字符串来判断当前行是否为子行。
  2. 处理列索引小于等于2的情况

    • 如果当前行有子行 (

      row.children
      

      ),进一步检查当前行是否展开 (

      row.expanded
      

      ):

      • 如果展开,返回 rowspan 为子行数加1,colspan 为1。
      • 如果未展开,返回 rowspancolspan 都为1。
    • 如果当前行是子行,返回 rowspancolspan 都为0,表示不显示该单元格。

    • 如果当前行既不是子行也没有子行,返回 rowspancolspan 都为1。

  3. 处理列索引大于2的情况

    • 默认返回 rowspancolspan 都为1。
    const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
      // 判断当前行是否为子行
      const isChildRow = row.first === "";
      
      // 如果列索引小于等于2 这里因为是前三列数据需要合并
      if (columnIndex <= 2) {
        // 如果当前行有子行
        if (row.children) {
          // 如果当前行是展开状态
          if (row.expanded) {
            return {
              rowspan: row.children.length + 1, // 合并行数为子行数加1
              colspan: 1, // 合并列数为1
            };
          } else {
            return {
              rowspan: 1, // 合并行数为1
              colspan: 1, // 合并列数为1
            };
          }
        } else if (isChildRow) {
          // 如果当前行是子行
          return {
            rowspan: 0, // 不显示该单元格
            colspan: 0, // 不显示该单元格
          };
        } else {
          // 如果当前行既不是子行也没有子行
          return {
            rowspan: 1, // 合并行数为1
            colspan: 1, // 合并列数为1
          };
        }
      }
      
      // 对于列索引大于2的情况,默认返回合并行数和列数都为1
      return {
        rowspan: 1,
        colspan: 1,
      };
    };
    
2. expand-change

当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded)

  • 保证数据状态同步:在行展开或折叠时,更新 row.expanded 属性可以让合并单元格的逻辑(如 objectSpanMethod)根据当前状态返回正确的 rowspancolspan 值。
  • 刷新布局保证显示正确:由于 Vue 更新 DOM 是异步的,使用 nextTick 确保在数据更新后再调用表格组件的 doLayout 方法,避免因布局未刷新而出现错位问题。
  • 应对树形结构合并单元格:对于存在 children 的行,其展开/折叠状态直接影响整个表格的显示效果,因此立即刷新布局可以确保所有合并单元格重新计算后显示正常。
const handleExpandChange = (row, expanded) => {
  if (row.children) {
    row.expanded = expanded;
// 使用 nextTick 包裹一个回调函数,确保在 Vue 完成 DOM 更新之后再刷新表格布局。
    nextTick(() => {
      // 如果 el-table 提供 doLayout 方法则调用刷新布局
      tableRef.value?.doLayout && tableRef.value.doLayout();
    });
  }
};

全部代码:

<template>
  <el-table
    ref="tableRef"
    :data="originalData"
    style="width: 100%; margin-bottom: 20px"
    row-key="id"
    border
    :span-method="objectSpanMethod"
    :tree-props="{ children: 'children' }"
    @expand-change="handleExpandChange"
  >
    <el-table-column prop="first" label="一级指标" />
    <el-table-column prop="directDeductPoint" label="一级指标扣分范围" />
    <el-table-column prop="relatedProcessVOS" label="一级指标关联流程" />
    <el-table-column prop="second" label="二级指标" />
    <el-table-column prop="third" label="三级指标" />
    <el-table-column prop="evalDesc" label="考核说明" />
    <el-table-column prop="deductType" label="考核扣分范围" />
    <el-table-column prop="enableYn" label="是否启用" />
  </el-table>
</template>

<script lang="ts" setup>
import { ref, nextTick } from "vue";

// 获取表格组件 ref
const tableRef = ref(null);

const originalData = ref([
  {
    id: 1,
    first: "一级指标1111",
    directDeductPoint: "一级指标扣分范围1111",
    relatedProcessVOS: "一级指标关联流程1111",
    second: " 二级指标1111",
    third: "三级指标1111",
    evalDesc: "考核说明1111",
    deductType: "考核扣分范围1111",
    enableYn: "是",
  },
  {
    id: 2,
    first: "一级指标2222",
    directDeductPoint: "一级指标扣分范围2222",
    relatedProcessVOS: "一级指标关联流程2222",
    second: "",
    third: " ",
    evalDesc: "",
    deductType: "",
    enableYn: "",
    children: [
      {
        id: 31,
        first: "",
        directDeductPoint: "",
        relatedProcessVOS: "",
        second: "二级指标212121",
        third: "三级指标212121",
        evalDesc: "考核说明212121",
        deductType: "考核扣分范围212121",
        enableYn: "是",
      },
      {
        id: 32,
        first: "",
        directDeductPoint: "",
        relatedProcessVOS: "",
        second: "二级指标222222",
        third: " 三级指标222222",
        evalDesc: "考核说明222222",
        deductType: "考核扣分范围222222",
        enableYn: "是",
      },
    ],
  },
  {
    id: 3,
    first: "一级指标3333",
    directDeductPoint: "一级指标扣分范围3333",
    relatedProcessVOS: "一级指标关联流程3333",
    second: "二级指标3333",
    third: "三级指标3333",
    evalDesc: "考核说明3333",
    deductType: "考核扣分范围3333",
    enableYn: "是",
  },
  {
    id: 4,
    first: "一级指标4444",
    directDeductPoint: "一级指标扣分范围4444",
    relatedProcessVOS: "一级指标关联流程4444",
    second: "二级指标4444",
    third: "三级指标4444",
    evalDesc: "考核说明4444",
    deductType: "考核扣分范围4444",
    enableYn: "是",
  },
  {
    id: 5,
    first: "一级指标5555",
    directDeductPoint: "一级指标扣分范围5555",
    relatedProcessVOS: "一级指标关联流程5555",
    second: "二级指标5555",
    third: "三级指标5555",
    evalDesc: "考核说明5555",
    deductType: "考核扣分范围5555",
    enableYn: "是",
  },
]);

const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
  const isChildRow = row.first === "";
  if (columnIndex <= 2) {
    if (row.children) {
      if (row.expanded) {
        return {
          rowspan: row.children.length + 1,
          colspan: 1,
        };
      } else {
        return {
          rowspan: 1,
          colspan: 1,
        };
      }
    } else if (isChildRow) {
      return {
        rowspan: 0,
        colspan: 0,
      };
    } else {
      return {
        rowspan: 1,
        colspan: 1,
      };
    }
  }
  return {
    rowspan: 1,
    colspan: 1,
  };
};

const handleExpandChange = (row, expanded) => {
  console.log("handleExpandChange", row, expanded);
  if (row.children) {
    row.expanded = expanded;
    nextTick(() => {
      // 如果 el-table 提供 doLayout 方法则调用刷新布局
      tableRef.value?.doLayout && tableRef.value.doLayout();
    });
  }
};
</script>

<style lang="scss" scoped>
.cus-table {
  :deep(.cell) {
    color: #002f59;
  }
  .table-column-btn {
    :deep(.kui-link--primary) {
      color: #005bac;
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2304876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型

前言 在干旱研究中&#xff0c;一个关键的科学问题是&#xff1a;在某一地区发生不同等级的气象干旱时&#xff0c;气象干旱会以何种概率引发不同等级的水文干旱、农业干旱和地下水干旱&#xff1f;换句话说&#xff0c;气象干旱的不同程度会分别引发其他类型干旱的哪种等级&a…

系统学习算法:专题十二 记忆化搜索

什么是记忆化搜索&#xff0c;我们先用一道经典例题来引入&#xff0c;斐波那契数 题目一&#xff1a; 相信一开始学编程语言的时候&#xff0c;就一定碰到过这道题&#xff0c;在学循环的时候&#xff0c;我们就用for循环来解决&#xff0c;然后学到了递归&#xff0c;我们又…

c++入门-------命名空间、缺省参数、函数重载

C系列 文章目录 C系列前言一、命名空间二、缺省参数2.1、缺省参数概念2.2、 缺省参数分类2.2.1、全缺省参数2.2.2、半缺省参数 2.3、缺省参数的特点 三、函数重载3.1、函数重载概念3.2、构成函数重载的条件3.2.1、参数类型不同3.2.2、参数个数不同3.2.3、参数类型顺序不同 前言…

51单片机测试题AI作答测试(DeepSeek Kimi)

单片机测试题 DeepSeek Kimi 单项选择题 &#xff08;10道&#xff09; 6题8题判断有误 6题判断有误 智谱清言6题靠谱&#xff0c;但仔细斟酌&#xff0c;题目出的貌似有问题&#xff0c;详见 下方。 填空题 &#xff08;9道&#xff09; 脉宽调制&#xff08;Pulse …

去耦电容的作用详解

在霍尔元件的实际应用过程中&#xff0c;经常会用到去耦电容。去耦电容是电路中装设在元件的电源端的电容&#xff0c;其作用详解如下&#xff1a; 一、基本概念 去耦电容&#xff0c;也称退耦电容&#xff0c;是把输出信号的干扰作为滤除对象。它通常安装在集成电路&#xf…

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷(二)

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷&#xff08;二&#xff09; 第一部分&#xff1a;网络平台搭建与设备安全防护任务书第二部分&#xff1a;网络安全事件响应、数字取证调查、应用程序安全任务书任务 1&#xff1a;应急响应&…

深入剖析:基于红黑树实现自定义 map 和 set 容器

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; 在 C 标准模板库&#xff08;STL&#xff09;的大家庭里&#xff0c;map和set可是超级重要的关联容器成员呢&#x1f60e;&#x…

20-R 绘图 - 饼图

R 绘图 - 饼图 R 语言提供来大量的库来实现绘图功能。 饼图&#xff0c;或称饼状图&#xff0c;是一个划分为几个扇形的圆形统计图表&#xff0c;用于描述量、频率或百分比之间的相对关系。 R 语言使用 pie() 函数来实现饼图&#xff0c;语法格式如下&#xff1a; pie(x, l…

第438场周赛:判断操作后字符串中的数字是否相等、提取至多 K 个元素的最大总和、判断操作后字符串中的数字是否相等 Ⅱ、正方形上的点之间的最大距离

Q1、判断操作后字符串中的数字是否相等 1、题目描述 给你一个由数字组成的字符串 s 。重复执行以下操作&#xff0c;直到字符串恰好包含 两个 数字&#xff1a; 从第一个数字开始&#xff0c;对于 s 中的每一对连续数字&#xff0c;计算这两个数字的和 模 10。用计算得到的新…

软考教材重点内容 信息安全工程师 第17章 网络安全应急响应技术原理与应用

17.1 网络安全应急响应概述 网络安全应急响应是针对潜在发生的网络安全事件而采取的网络安全措施。 17.1.1 网络安全应急响应概念 网络安全应急响应是指为应对网络安全事件&#xff0c;相关人员或组织机构对网络安全事件进行监测、预警、分析、响应和恢复等工作。 17.2.3 网络安…

点击修改按钮图片显示有问题

问题可能出在表单数据的初始化上。在 ave-form.vue 中&#xff0c;我们需要处理一下从后端返回的图片数据&#xff0c;因为它们可能是 JSON 字符串格式。 vue:src/views/tools/fake-strategy/components/ave-form.vue// ... existing code ...Watch(value)watchValue(v: any) …

Node.js技术原理分析系列——Node.js的perf_hooks模块作用和用法

Node.js 是一个开源的、跨平台的 JavaScript 运行时环境&#xff0c;它允许开发者在服务器端运行 JavaScript 代码。Node.js 是基于 Chrome V8 引擎构建的&#xff0c;专为高性能、高并发的网络应用而设计&#xff0c;广泛应用于构建服务器端应用程序、网络应用、命令行工具等。…

用DeepSeek来帮助学习three.js加载3D太极模形

画一个平面的太极图是很容易&#xff0c;要实现3D的应该会很难 一、参考3D模形效果 看某网页看到一个效果&#xff0c;像一个3D太极球&#xff0c;觉得挺有趣&#xff0c;挺解压的&#xff0c;想进一步去了解下这是如何实现 效果&#xff1a; 链接地址&#xff1a; http://www.…

【JavaEE进阶】Spring Boot配置文件

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗 如有错误&#xff0c;欢迎指出~ 目录 SpringBoot配置⽂件 举例: 通过配置文件修改端口号 配置⽂件的格式 properties基本语法 读取配置⽂件 properties配置文件的缺点 yml配置⽂件 yml基本语法 yml和proper…

学习通用多层次市场非理性因素以提升股票收益预测

“Learning Universal Multi-level Market Irrationality Factors to Improve Stock Return Forecasting” 论文地址&#xff1a;https://arxiv.org/pdf/2502.04737 Github地址&#xff1a;https://github.com/lIcIIl/UMI 摘要 深度学习技术与量化交易相结合&#xff0c;在股…

【Godot4.3】基于绘图函数的矢量蒙版效果与UV换算

概述 在设计圆角容器时突发奇想&#xff1a; 将圆角矩形的每个顶点坐标除以对应圆角矩形所在Rect2的size&#xff0c;就得到了顶点对应的UV坐标。然后使用draw_colored_polygon&#xff0c;便可以做到用图片填充圆角矩形的效果。而且这种计算的效果就是图片随着其填充的图像缩…

DeepSeek开源周Day1:FlashMLA引爆AI推理性能革命!

项目地址&#xff1a;GitHub - deepseek-ai/FlashMLA 开源日历&#xff1a;2025-02-24起 每日9AM(北京时间)更新&#xff0c;持续五天&#xff01; ​ 一、开源周震撼启幕 继上周预告后&#xff0c;DeepSeek于北京时间今晨9点准时开源「FlashMLA」&#xff0c;打响开源周五连…

通过恒定带宽服务器调度改进时间敏感网络(TSN)流量整形

论文标题 英文标题&#xff1a;Improving TSN Traffic Shaping with Constant Bandwidth Server Scheduling 中文标题&#xff1a;通过恒定带宽服务器调度改进时间敏感网络&#xff08;TSN&#xff09;流量整形 作者信息 作者&#xff1a;Benjamin van Seggelen 指导教师&am…

如何查看图片的原始格式

问题描述&#xff1a;请求接口的时候&#xff0c;图片base64接口报错&#xff0c;使用图片url请求正常 排查发现是图片格式的问题&#xff1a; 扩展名可能被篡改&#xff1a;如果文件损坏或扩展名被手动修改&#xff0c;实际格式可能与显示的不同&#xff0c;需用专业工具验证…

赛前启航 | 三场重磅直播集结,予力微软 AI 开发者挑战赛!

随着微软 AI 开发者挑战赛的火热进行&#xff0c;赛前指导直播已成为众多参赛者获取技术干货、灵感碰撞和实战技巧的绝佳平台。继前两期的精彩呈现&#xff0c;第三、四、五期直播即将接连登场&#xff0c;为开发者们带来更加深入的 AI 技术剖析和项目实战指引。无论你是想进一…