背景:项目中需要针对相等的行和列自行合并,上下相等的单元格进行行合并,左右相等的单元格进行列合并。效果如下图所示
span-method介绍
el-table想实现合并行列,就绕不开span-method,官方文档介绍如下
通过给
table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,第二个元素代表colspan。 也可以返回一个键名为rowspan和colspan的对象。Function({ row, column, rowIndex, columnIndex })
简单来说,span-method会遍历每一个单元格,
- 返回 [0, 0], 不渲染此单元格,被合并
- 返回 [n, 1],行合并效果,占n行
- 返回 [1, n],列合并效果,占n列
- 返回 [1, 1],正常渲染单元格,无合并效果
理解了span-method原理,下面来看核心思路
自动合并实现思路
通过span-method方法,每个单元格都返回自己的rowspan和colspan
查找前一行,判断当前与前一行是否相等,相等则返回[0,0],则不显示,被合并
默认rowspan为1(n=1),查找之后还有多少行和当前行相等,返回[n, 1],则实现合并行
所有上下相邻值相等的行都合并完成;
列合并思路同上
查找前一列prop,判断当前列值是否与前一列prop值相等,相等则返回[0,0],则不显示,被合并
默认colspan为1(n=1),查找之后有多少列和当前列的值相同,返回[1, n],进行合并
所有左右相邻值相等的列都合并完成;
span-method代码如下
const objectSpanMethod = ({
row,
column,
rowIndex,
columnIndex,
}: SpanMethodProps) => {
// 此例针对前三列进行操作
if (columnIndex >= 0 && columnIndex <= 2) {
// 行合并逻辑
// 查找前一行
const previousRow = rowIndex > 0 ? tableData.value[rowIndex - 1] : null
// 判断当前行和前一行的值是否相同
if (previousRow && previousRow[column.property] === row[column.property]) {
return [0, 0] // 如果相同,返回 [0, 0] 表示不显示此单元格
}
// 查找之后有多少行和当前行的值相同,进行合并
let rowspan = 1
for (let i = rowIndex + 1; i < tableData.value.length; i++) {
if (tableData.value[i][column.property] === row[column.property]) {
rowspan++
} else {
break
}
}
// 列合并逻辑
// 查找前一列prop - 针对日期列前列
const previousProp =
columnIndex > 0 ? columns.value[columnIndex - 1].prop : null
// 判断当前列与前一列的值是否相同
if (previousProp && row[previousProp] === row[column.property]) {
return [0, 0]
}
// 查找之后有多少列和当前列的值相同,进行合并
let colspan = 1
for (let i = columnIndex + 1; i <= 2; i++) {
if (row[columns.value[i].prop] === row[column.property]) {
colspan++
} else {
break
}
}
return [rowspan, colspan] // 合并的行数 rowspan 不需合并列的返回
}
}