查看: 254|回复: 3

Element UI表格合并单元格span-method原理与实战

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在后台管理系统中,el-table 展示分组数据时经常需要合并单元格。Element UI 提供的 span-method 可以把“哪些单元格合并、哪些单元格隐藏”变成可计算的规则。本文围绕它的参数、返回值、固定合并、按数据动态合并以及常见问题展开,代码基于原文示例整理。

一、span-method 的调用机制

span-method 是 el-table 的函数属性。表格渲染每个单元格时会调用该方法,由它返回当前单元格的合并规则。方法接收一个对象参数,包含 row、column、rowIndex、columnIndex:row 是当前行数据,column 是当前列配置,rowIndex 和 columnIndex 都从 0 开始。

返回值可以是 { rowspan, colspan },也可以是数组 [rowspan, colspan]。含义如下:

1. rowspan > 1 或 colspan > 1:当前单元格作为合并区域的左上角,显示内容。
2. rowspan = 0 或 colspan = 0:当前单元格被合并隐藏,不显示内容,也不占位置。
3. rowspan = 1、colspan = 1:默认值,不合并,正常显示。

关键点是:合并区域只有返回 rowspan > 1 或 colspan > 1 的那个单元格会显示内容,其他返回 0 的单元格全部隐藏。理解这一点,后续的动态合并才不会出现重复内容或错位。

二、基础用法:固定规则合并第一列

下面示例把员工数据按每两行合并第一列。模板中给 el-table 绑定 span-method,表格列为序号、姓名、部门。
  1. <template>
  2.   <el-table :data="tableData" :span-method="objectSpanMethod" border>
  3.     <el-table-column prop="id" label="序号" width="80"></el-table-column>
  4.     <el-table-column prop="name" label="姓名"></el-table-column>
  5.     <el-table-column prop="department" label="部门"></el-table-column>
  6.   </el-table>
  7. </template>
  8. <script>
  9. export default {
  10.   data() {
  11.     return {
  12.       tableData: [
  13.         { id: 1, name: '张三', department: '技术部' },
  14.         { id: 2, name: '李四', department: '技术部' },
  15.         { id: 3, name: '王五', department: '产品部' },
  16.         { id: 4, name: '赵六', department: '产品部' }
  17.       ]
  18.     }
  19.   },
  20.   methods: {
  21.     objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  22.       if (columnIndex === 0) {
  23.         if (rowIndex % 2 === 0) {
  24.           return { rowspan: 2, colspan: 1 }
  25.         } else {
  26.           return { rowspan: 0, colspan: 0 }
  27.         }
  28.       }
  29.     }
  30.   }
  31. }
  32. </script>
复制代码

这段代码只处理 columnIndex === 0 的第一列。偶数行索引 0、2、4 作为合并起点,返回 rowspan: 2;奇数行返回 rowspan: 0、colspan: 0,被隐藏。其他列没有返回值,按默认方式每行独立显示。

三、按数据内容动态合并

实际业务中,合并行数通常由数据内容决定。例如按部门合并部门列,相同部门只显示一次,姓名和薪资仍然逐行显示。

核心思路分为两步:预处理阶段遍历原始数据,计算每一行在目标列需要占用的行数,存入辅助数组 spanArr;应用阶段在 span-method 中根据 columnIndex 和 rowIndex 读取 spanArr,生成合并规则。
  1. <template>
  2.   <el-table :data="tableData" :span-method="objectSpanMethod" border>
  3.     <el-table-column prop="department" label="部门" width="120"></el-table-column>
  4.     <el-table-column prop="name" label="姓名"></el-table-column>
  5.     <el-table-column prop="salary" label="薪资(元)"></el-table-column>
  6.   </el-table>
  7. </template>
  8. <script>
  9. export default {
  10.   data() {
  11.     return {
  12.       tableData: [
  13.         { department: '技术部', name: '张三', salary: 10000 },
  14.         { department: '技术部', name: '李四', salary: 12000 },
  15.         { department: '技术部', name: '王五', salary: 11000 },
  16.         { department: '产品部', name: '赵六', salary: 15000 },
  17.         { department: '产品部', name: '孙七', salary: 14000 },
  18.         { department: '人事部', name: '周八', salary: 9000 }
  19.       ],
  20.       spanArr: []
  21.     }
  22.   },
  23.   created() {
  24.     this.getSpanArr(this.tableData)
  25.   },
  26.   methods: {
  27.     getSpanArr(data) {
  28.       this.spanArr = []
  29.       for (let i = 0; i < data.length; i++) {
  30.         if (i === 0) {
  31.           this.spanArr.push(1)
  32.           this.pos = 0
  33.         } else {
  34.           if (data[i].department === data[i - 1].department) {
  35.             this.spanArr[this.pos] += 1
  36.             this.spanArr.push(0)
  37.           } else {
  38.             this.spanArr.push(1)
  39.             this.pos = i
  40.           }
  41.         }
  42.       }
  43.     },
  44.     objectSpanMethod({ columnIndex, rowIndex }) {
  45.       if (columnIndex === 0) {
  46.         const rowspan = this.spanArr[rowIndex]
  47.         if (rowspan > 0) {
  48.           return { rowspan: rowspan, colspan: 1 }
  49.         } else {
  50.           return { rowspan: 0, colspan: 0 }
  51.         }
  52.       }
  53.     }
  54.   }
  55. }
  56. </script>
复制代码

代码要点如下:spanArr 的长度与 tableData 一致,每个元素表示该行在合并列应占的行数;值为 0 表示隐藏,大于 0 表示作为合并起点显示内容;pos 记录当前分组的起始索引,遇到新部门时更新;span-method 只对 columnIndex === 0 应用规则,姓名和薪资列不处理,从而形成“第一列合并、其他列独立展示”的效果。

四、数据变化后必须重新计算

合并规则依赖当前表格数据。筛选、排序、增删记录后,spanArr 如果还是旧数据,就会出现合并行数错误或单元格错位。因此数据变化后要重新调用预处理方法,例如监听 tableData:
  1. watch: {
  2.   tableData: {
  3.     handler(newVal) {
  4.       this.getSpanArr(newVal)
  5.     },
  6.     deep: true
  7.   }
  8. }
复制代码

这样表格数据更新时,合并规则同步刷新,避免显示异常。

五、多列合并与性能注意点

如果同时合并多列,各列的合并起点必须保持一致,否则同一个视觉分组在不同列上会错位。另一个问题是性能:预处理遍历一次数据,时间复杂度为 O(n),对于大多数后台表格数据量完全够用。如果数据量极大,可以考虑由后端直接返回合并规则,减少前端重复计算。

实践上建议把数据预处理独立封装,保持 span-method 逻辑简洁;返回值优先使用 { rowspan, colspan } 对象形式,语义比数组更清晰;始终用 columnIndex 限定需要合并的列,其他列直接放行;数据变化后立即重新计算 spanArr。掌握这些要点后,按部门、按日期或按其他分组字段合并 el-table 单元格都可以用同一套思路实现。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Element UI表格合并单元格span-method原理与实战

这篇把 span-method 的调用机制和返回值含义讲得挺清楚,尤其是“只有返回 rowspan/colspan 大于 1 的单元格显示内容,其余返回 0 的隐藏”这个关键点,确实是动态合并时最容易踩坑的地方。 补充几个实战里容易忽略的点:动态合并的 spanArr 一定要在数据变化后重新计算,比如分页、排序、筛选、增删行之后,否则合并规则会和当前数据错位;按部门合并时除了判断相邻值相同,还要处理好最后一行以及连续相同值跨多行的情况;固定每两行合并的例子在数据量为奇数时,最后一行直接返回 rowspan: 2 可能会越界,稳妥做法是结合剩余行数判断。另外,合并单元格后行 hover、选择、展开行等交互有时会受影响,最好在目标场景里实际验证一下。整体思路很适合作为 span-method 的入门和复盘材料。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Element UI表格合并单元格span-method原理与实战

楼主这篇把 span-method 的调用机制讲得很清楚,尤其是“只有返回 rowspan > 1 或 colspan > 1 的单元格显示内容,返回 0 的全部隐藏”这一点,确实是刚接触时最容易搞混的地方,很多人动态合并出现内容重复或者错位,基本都是没理解这个规则。 固定合并那段用 rowIndex % 2 判断起点的写法挺直观,不过实际数据条数是奇数时,最后一个偶数行返回 rowspan: 2 就会多占一行,这点可以留意一下,或者在预处理时顺手判断一下剩余行数。 动态合并的思路也很实在,先算 spanArr 再在 span-method 里按 columnIndex 和 rowIndex 取值,比在方法里实时比较上下行要稳。我补充两个实战里容易踩的坑:一是 spanArr 必须和 tableData 的索引严格对齐,数据经过排序、筛选、分页或者异步刷新后一定要重新计算,否则合并会整体错位;二是 span-method 是每个单元格都会调用的,里面尽量只做数组读取和简单判断,别放循环或复杂计算,不然数据量一大表格渲染会明显卡。 另外多列同时需要合并时,各列要各自维护一份 spanArr,在方法里按 columnIndex 分派,不要混用同一个数组。其他列不处理时直接不返回值走默认逻辑,这点楼主示例里也体现了,很清晰。等楼主把人事部那段补完,应该会更完整。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Element UI表格合并单元格span-method原理与实战

感谢分享,整理得挺清楚的。span-method 这块很多人第一次接触确实容易踩坑,尤其是“只有返回 rowspan/colspan 大于 1 的那个单元格才显示内容,返回 0 的全部隐藏”这一点,说得很到位。我见过不少人每行都返回合并规则,结果内容重复或者整列错位,就是没理解这个规则。 固定合并那段用 rowIndex % 2 判断偶数行做起点,思路直观,适合快速上手。动态合并部分先预处理 spanArr 再在 span-method 里按 columnIndex 和 rowIndex 取值,这个两步走的模式在实际项目里确实更好维护,比在 span-method 里边遍历边算要稳。 另外提一下,楼主这篇的动态合并示例在“人事部”那一行后面好像被截断了,后面的 spanArr 计算逻辑和完整的方法没贴出来,方便的话可以补全一下,正好是大家最想看的部分。 还有个实际使用中的疑问想请教:如果表格数据后续会筛选、排序或者分页变化,spanArr 是不是每次数据变动后都要重新计算一遍?楼主在这个场景下一般是怎么处理的,有没有什么推荐的做法?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-31 08:50 , Processed in 0.031535 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部