相信很多人都有被elementui的合并表格搞疯过,合并了这一列的表格,别的单元格又出问题,这次记录一下我排查错误的过程。
首先,需要的效果是这样的
如果没写过合并表格的同学,可以先去翻阅一下elementui官网看看是通过什么方法合并的(span-method),也看看数据的结构应该怎么设计,有基础的同学可以直接看疑问2或者总结。
拿到这个需求,很明显我们要去写一个table
js
<el-table
:data="templateTableData"
style="width: 100%"
border
:span-method="objectSpanMethod"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="40"> </el-table-column>
<el-table-column prop="summaryName" label="摘要" width="400">
</el-table-column>
<el-table-column prop="voucherSubjectName" label="科目">
</el-table-column>
<el-table-column prop="voucherWordName" label="方向" width="180">
</el-table-column>
<el-table-column prop="loanAmount" label="金额" width="180">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150"
align="center"
>
<template slot-scope="scope">
<el-button type="text" @click="modifyHandler(scope.row)"
>修改</el-button
>
<el-button type="text" @click="deleteHandler(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
疑问1:我怎么知道一条数据占几行,先来看后端返回的数据
后端是一条一条返回的,但是需要合并的数据,会有个id是一样的,比如我这里,第一条数据占3行,第二条数据占4行,第三条数据占5行,那么第一条数据都有一个id是一样并且是唯一的,第二第三行也一样,比如我这里的结构是这样的
js
const tableData = [
{ voucherId: '1', summaryName: '合计1', },
{ voucherId: '1', summaryName: '名字1-1', voucherSubjectName: '科目1', voucherWordName: '记', loanAmount: 1 },
{ voucherId: '1', summaryName: '名字1-2', voucherSubjectName: '科目2', voucherWordName: '记', loanAmount: 2 },
{ voucherId: '2', summaryName: '合计2', voucherSubjectName: '科目3', voucherWordName: '记', loanAmount: 3 },
{ voucherId: '2', summaryName: '名字2-1', voucherSubjectName: '科目4', voucherWordName: '记', loanAmount: 4 },
{ voucherId: '2', summaryName: '名字2-2', voucherSubjectName: '科目5', voucherWordName: '记', loanAmount: 5 },
{ voucherId: '2', summaryName: '名字2-3', voucherSubjectName: '科目6', voucherWordName: '记', loanAmount: 6 },
{ voucherId: '3', summaryName: '合计3', voucherSubjectName: '科目7', voucherWordName: '记', loanAmount: 7 },
{ voucherId: '3', summaryName: '名字3-1', voucherSubjectName: '科目8', voucherWordName: '记', loanAmount: 8 },
{ voucherId: '3', summaryName: '名字3-2', voucherSubjectName: '科目9', voucherWordName: '记', loanAmount: 9 },
{ voucherId: '3', summaryName: '名字3-3', voucherSubjectName: '科目10', voucherWordName: '记', loanAmount: 10 },
{ voucherId: '3', summaryName: '名字3-4', voucherSubjectName: '科目11', voucherWordName: '记', loanAmount: 11 },
]
这里需要写一个方法,去获取需要合并的行,复制可直接使用
js
computed: {
mergingCols() {
const mergingCols = [];
let mergingPos = 0;
for (let i = 0; i < this.tableData.length; i++) {
if (i === 0) {
mergingCols.push(1);
mergingPos = 0;
} else {
if (
this.tableData[i].voucherId === this.tableData[i - 1].voucherId
) {
mergingCols[mergingPos] += 1;
mergingCols.push(0);
} else {
mergingCols.push(1);
mergingPos = i;
}
}
}
return mergingCols;
},
},
mergingCols返回的数据就是这样的:
意思就是第0个index需要合并3条数据,第3个index开始就是第二条数据,需要合并4条数据,第8个index表示第三行,需要合并5条数据,这里的0就是表示被合并的行。
疑问2:我当时错误合并方式是什么?
按照需求,需要的是第一列的selection合并,然后每条数据的第一行摘要占满科目、方向和余额这几列,最后操作列再合并。
那我去循环mergingCols的时候,当columnIndex为0和5的时候去合并mergingCols不为0的行数(合并selection和操作列),当遇到columnIndex为1的时候,合并3列,即1-4列,不就完了,说干就干。
js
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0 || columnIndex == 5) {
if (this.mergingCols[rowIndex] > 0) {
return [this.mergingCols[rowIndex], 1];
} else {
//遇到0就不管啦
return [0, 0];
}
} else if (columnIndex == 1) {
if (this.mergingCols[rowIndex] > 0) {
return [1, 4];
}
}
},
写出来之后就烦恼了,操作列空了。然后自顾自调了好久都没调出来,后来打开控制台查看元素。

重点来了
来看第一条数据,好几个单元格跑外面去了,很明显是被撑出去的,但是操作列的第一行单元格还在,第二行第三行的数据没有和第一行合并在一起,反而被挤出去了,而且合并的应该是index为0-2的列,但是实际是1-3,这种情况大概率是某些单元格没有意义,应该被清除的,但是没清除还留在表格里,所以就被撑出去了。

然后我对着元素审查手动删除了几个单元格,正常了!!!

是什么情况???我们删除的元素是el-table_1_column_3、el-table_1_column_4、el-table_1_column_5,也就是说当columnIndex为2、3、4(el-table_1_column是从1开始的)的时候我没有return [0,0]清除掉一些因为第一行合并了三列单元格而撑出去的原来的元素,很明显我要再添加一个else,然后清除多余的元素。
js
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
console.log('columnIndex',columnIndex)
if (columnIndex == 0 || columnIndex == 5) {
if (this.mergingCols[rowIndex] > 0) {
return [this.mergingCols[rowIndex], 1];
} else {
return [0, 0];
}
} else if (columnIndex == 1) {
if (this.mergingCols[rowIndex] > 0) {
return [1, 4];
}
}
//加上else
else {
return [0, 0];
}
},
事与愿违,这些操作列好了,但是2、3、4列全出问题了,应该是有些单元格是需要保持原样的,但是被我给无情清除掉了。因为class后的index极度不连贯。

结合上面,我应该是要在2、3、4列的时候,并且只清掉第一行因为摘要合并了科目、方向、余额 多出的单元格,只需要在上面的else再添加一个条件。
js
else {
//每条数据的第一行
if (this.mergingCols[rowIndex] > 0) {
return [0, 0];
}
}
最后总结
当我们在做合并表格的时候,如果有些单元格变成了空白,应该打开F12,查看元素,大概率是前面有合并单元,合并后,多出来一些无意义的单元格给顶出去了,要尝试手动delete一些元素,然后分析这些元素的class对应的column的index,这些tr里面的td会超出我们预期的数量。像下面这样,第一行合并完之后应该只有3个单元格,但是出现了6个
当检查到class不连贯,跳跃很大,并且td少于预期的数量,很明显是被自己误清除了一些有意义的单元格,这时要看代码里面return [0,0]的条件是否符合逻辑,像这个。
以上是我自己在做合并单元格时的一些检查思路,希望对大家有用。