使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan
使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan
背景
在使用Ant Design Vue 开发数据表格时,我们常常会遇到需要合并单元格的需求。
比如,某些字段的值可能会在多行中重复出现,而我们希望将这些重复的单元格合并为一个单元格。
通过自定义渲染函数和数据处理来实现
rowSpan
合并。
具有共同上级菜单的单元格进行合并展示
真实环境 具有相同上级菜单的单元格进行合并
模拟数据
环境准备
表格 Table - Ant Design Vue
首先,确保你已经安装了 Ant Design Vue。如果你还没有安装,可以通过以下命令安装:
npm install ant-design-vue --save
接下来,确保在你的 Vue 项目中正确引入 Ant Design Vue:
import { Table } from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
表格结构及需求
这里我是用假数据模拟,假设我们有一个表格,需要展示以下数据:
const items = [{ parentName: '父级菜单1', menuName: '菜单名称1', address: 'New York' },{ parentName: '父级菜单1', menuName: '菜单名称2', address: 'Los Angeles' },{ parentName: '父级菜单2', menuName: '菜单名称3', address: 'Chicago' },{ parentName: '父级菜单2', menuName: '菜单名称4', address: 'San Francisco' },{ parentName: '父级菜单3', menuName: '菜单名称5', address: 'Seattle' },
];
在这张表中,parentName
字段存在多个相同的值,我们希望对相同的 parentName
进行单元格合并操作。最终效果是:父级菜单1
和 父级菜单2
的两行 parentName
将合并成一个单元格。
代码实现
数据处理:计算 rowSpan
为了实现合并单元格,我们需要根据相同字段的连续行数动态计算每个单元格的 rowSpan
属性。
我们将通过一个名为 processTableData
的函数来处理数据。
需要重新处理我们的源数据,将parentName相同的行rowSpan记录起来,同时将不需要展示的单元格rowSpan重置为0
表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。
const processTableData = data => {let result = [];let i = 0;while (i < data.length) {const currentItem = data[i];let rowSpan = 1;//// 计算当前 parentName 后续相同的行数while (i + rowSpan < data.length && data[i + rowSpan].parentName === currentItem.parentName) {rowSpan++;}// 为当前项设置 rowSpan,记录相同的行数量,result.push({...currentItem,rowSpan});// !!!重点!!!合并的行都需要保留,但是这些保留的单元不需要渲染,设置rowSpan为0for (let j = 1; j < rowSpan; j++) {result.push({...data[i + j],rowSpan: 0 // 后续行不需要合并});}// 跳过已经合并的行,i += rowSpan;}return result;
};
表格列配置:自定义渲染
在 Ant Design Vue 的 Table
组件中,我们可以使用 customRender
来对某列的渲染进行自定义。我们将使用 rowSpan
来控制每个单元格的合并效果。
表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。
customRender
可以和jsx进行类比,这个函数可以返回html元素结构
Function(text, record, index) {}|slot-scope
生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并,可参考 表格 Table - Ant Design Vue 表格行/列合并
scopedSlots
使用 columns 时,可以通过该属性配置支持 slot-scope 的属性,如
scopedSlots: { customRender: 'XXX'}
配合a-table组件插槽使用
const columns = [{title: '父级菜单',dataIndex: 'parentName',// 自定义渲染函数,和jsx类似customRender: (text, record) => {return {children: text,attrs: {// 当rowSpan的值为零时,不渲染单元格,为其它值时,进行跨行rowSpan: record.rowSpan;// 获取通过processTableData处理后的rowSpan值,注意这里小驼峰命名}};}},{title: '菜单名称',key: 'menuName',width: 220,dataIndex: 'menuName',align: 'left',// 插槽渲染scopedSlots: { customRender: 'beautiful' },ellipsis: true},{title: 'Address',dataIndex: 'address',// 插槽渲染scopedSlots: { customRender: 'beautiful' },}
];
完整代码
经过上面的步骤,我们实现最终效果
最后,我们将处理过的数据传递给 Table
组件,并在模板中进行渲染。
<template><a-table style="background-color: white" :bordered="true" :columns="columns" :dataSource="tableDataList" :rowKey="(record, index) => index"><template slot="beautiful" slot-scope="scope">{{ scope }}</template></a-table>
</template><script>
export default {components: {},data() {const items = [{ parentName: '父级菜单1', menuName: '菜单名称1', key: Math.random(), address: 'New York' },{ parentName: '父级菜单1', menuName: '菜单名称2', key: Math.random(), address: 'Los Angeles' },{ parentName: '父级菜单2', menuName: '菜单名称3', key: Math.random(), address: 'Chicago' },{ parentName: '父级菜单2', menuName: '菜单名称4', key: Math.random(), address: 'San Francisco' },{ parentName: '父级菜单3', menuName: '菜单名称5', key: Math.random(), address: 'Seattle' }];const processedData = this.processTableData(items);return {tableDataList: processedData,columns: [{title: '父级菜单',dataIndex: 'parentName',// 自定义渲染函数,和jsx类似customRender: (text, record) => {return {children: text,attrs: {rowSpan: record.rowSpan // 获取通过processTableData处理后的rowSpan值,注意这里小驼峰命名}};}},{title: '菜单名称',key: 'menuName',width: 220,dataIndex: 'menuName',align: 'left',// 插槽渲染scopedSlots: { customRender: 'beautiful' },ellipsis: true},{title: 'Address',dataIndex: 'address',scopedSlots: { customRender: 'beautiful' }}]};},methods: {processTableData(data) {let result = [];let i = 0;while (i < data.length) {const currentItem = data[i];let rowSpan = 1; //// 计算当前 parentName 后续相同的行数while (i + rowSpan < data.length && data[i + rowSpan].parentName === currentItem.parentName) {rowSpan++;}// 为当前项设置 rowSpan,记录相同的行数量,result.push({...currentItem,rowSpan});// !!!重点!!!合并的行都需要保留,但是这些保留的单元不需要渲染,设置rowSpan为0for (let j = 1; j < rowSpan; j++) {result.push({...data[i + j],rowSpan: 0 // 后续行不需要合并});}// 跳过已经合并的行,i += rowSpan;}return result;}}
};
</script>
效果展示
总结
使用自定义渲染函数,结合数据可以实现单元格合并功能。
相关文章:

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan
使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan 背景 在使用Ant Design Vue 开发数据表格时,我们常常会遇到需要合并单元格的需求。 比如,某些字段的值可能会在多行中重复出现,而我们希望将这些重复的单元格合并为…...
相机光学(四十四)——ALL-PD和PDAF
1.PDAF(Phase Detection Auto Focus) PDAF是相位检测自动对焦技术的缩写,它是一种在数码相机和智能手机摄像头中使用的自动对焦技术。 PDAF的原理是根据CIS(CMOS图像传感器)不同像素的相位差信息,判断出…...

Opengl光照测试
代码 #include "Model.h" #include "shader_m.h" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" //以上是放在同目录的头文件#include <glad/glad.h> #include <GLFW/glfw3.…...
OpenSIP2.4.11 向 FreeSWITCH 注册
应朋友要求做了个简单的测试,花费时间不过半小时,记录如下: OpenSIPS IP 地址:192.168.31.213 FreeSWITCH IP 地址:192.168.31.166 加载 uac_registrant 模块(这个模块依赖 uac_auth 模块,得…...

【C++】深入理解 C++ 优先级队列、容器适配器与 deque:实现与应用解析
个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 📘 基础数据结构【C语言】 💻 C语言编程技巧【C】 🚀 进阶C【OJ题解】 📝 题解精讲 目录 前言📌 1. 优先级队列、容器适配器和 deque 概述✨1.1 什么是优…...
Android 开发与救砖工具介绍
Android 开发与救砖工具介绍 在 Android 开发和设备维护中,fastboot、adb 和 9008 模式是三个非常重要的工具和模式。它们各自有不同的用途和操作方式,对于开发者和技术支持人员来说,了解它们的功能和使用方法是必不可少的。 1. Fastboot …...
vue2和vue3:diff算法的区别?
Vue 2 和 Vue 3 在 diff 算法方面的主要区别是: Vue 2 使用普通的 diff 算法,它会遍历所有的节点进行比对。 Vue 3 引入了 patch flag 的概念,并且对 diff 算法进行了优化,比如在相同层级的节点间不会去递归比对已经被移除的节点…...
后端返回大数问题
这个问题并不难,但是在开发的时候没有注意到 后端返回了一个列表数据,包含id,这个id是一个大数,列表进入详情,需要将id传入到详情页面详情页面内部通过id获取数据一直404,id不正确找问题,从路由传参到请求数据发现id没有问题,然后和后端进行联调,发现后端返回的id和我获取的id…...

vue3: ref, reactive, readonly, shallowReactive
vue3: ref, reactive, readonly, shallowReactive 原文地址:https://mp.weixin.qq.com/s/S3jPZKEMBP8nQQObF5d2VA <template><!-- <ul><li v-for"item in list.arr">{{item}}</li></ul><button click.prevent"add"…...

5G与4G互通的桥梁:N26接口
5G的商用部署进程将是一个基于4G系统进行的长期的替换、升级、迭代的过程,4G系统是在过渡到5G全覆盖过程中,作为保障用户业务连续性体验这一目的的最好补充。 因此4G/5G融合组网,以及互操作技术将是各大运营商在网络演进中需要重点考虑的问题…...
29-Elasticsearch 集群监控
Elasticsearch Stats 相关的 API ● Elasticsearch 提供了多个监控相关的 API ○ Node Stats: _nodes/stats ○ Cluster Stats: _cluster/stats ○ Index Stats: index_name/_stats Elasticsearch Task API ● 查看 Task 相关的 API ○ Pending Cluster Tasks…...

利用Excel批量生成含二维码的设备管理标签卡片
在日常办公中,批量制作标签是常见且繁琐的任务,尤其当这些标签需要包含大量数据并附带二维码以便快速扫描识别时,难度更是成倍增加。尽管传统的Word邮件合并功能在数据插入方面表现出色,但在二维码生成上却显得有些捉襟见肘。 为…...

小米运动健康与华为运动健康在苹手机ios系统中无法识别蓝牙状态 (如何在ios系统中开启 蓝牙 相册 定位 通知 相机等功能权限,保你有用)
小米运动健康与华为运动健康在苹手机ios系统中无法识别蓝牙状态 (解决方案在最下面,参考蓝牙权限设置方式举一反三开启其它模块的权限) 最近买了一台小米手表s4,但是苹手机ios系统中的 “小米运动健康” app 始终无法识别我手机…...

高亮变色显示文本中的关键字
效果 第一步:按如下所示代码创建一个用来高亮显示文本的工具类: public class KeywordUtil {/*** 单个关键字高亮变色* param color 变化的色值* param text 文字* param keyword 文字中的关键字* return*/public static SpannableString highLigh…...

Javascript垃圾回收机制-运行机制(大厂内部培训版本)
前言 计算机基本组成: 我们编写的软件首先读取到内存,用于提供给 CPU 进行运算处理。 内存的读取和释放,决定了程序性能。 冯诺依曼结构 解释和编译 这两个概念怎么理解呢。 编译相当于事先已经完成了可以直接用。好比去饭店吃饭点完上…...
【jvm】一个空Object对象的占多大空间
目录 1. 说明2. 结论 1. 说明 1.在Java中,一个空Object对象所占用的内存空间大小会受到JVM(Java虚拟机)实现和配置的影响,具体数值可能因不同JVM版本和配置而有所不同。2.但一般来说,可以基于一些通用的原则来估算这个…...
241114.学习日志——[CSDIY] [CS]数据结构与算法 [00]
CSDIY:这是一个非科班学生的努力之路,从今天开始这个系列会长期更新,(最好做到日更),我会慢慢把自己目前对CS的努力逐一上传,帮助那些和我一样有着梦想的玩家取得胜利!!&…...

The Planets: Earth -- 练习
环境搭建 该靶场环境来自Vulnhub -------- Difficulty: Easy 靶机与Kali的IP地址只需要在同一局域网即可(同一个网段,即两虚拟机处于同一网络模式),所以需要调整KALI和靶场的网络模式,为了方便测试本地采用NAT模式。 注意&…...

linux逻辑卷练习
目录 知识点: 常用命令 题目: 解题: 1)分区 2)创建物理卷 3)创建卷组 4)生成逻辑卷 "要带参数 -n" 5)扩容 6)格式化(添加文件系统) 7)挂…...

openai 论文Scaling Laws for Neural Language Models学习
2001.08361 (arxiv.org) 论文研究语言模型在交叉熵损失下的性能经验缩放定律:模型损失(性能)随模型大小、数据集大小和用于训练的计算量呈现缩放为幂律的关系,有些趋势跨越超过 7 个数量级。其他模型架构细节 (如网络…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...