前言
最近有个需求,要对相同值的单元格进行合并,踩了一下坑,顺便记录一下,方便以后的使用。
欢迎留言,允许转载,转载麻烦说明来源,创作不易
实现
官方api
:span-method="objectSpanMethod"
objectSpanMethod({
row, column, rowIndex, columnIndex })
row
代表行属性,column
代表列属性,rowIndex
代表行下标,columnIndex
代表列下标
初始数据
<template>
<div>
<el-table :data="tableData" border style="width: 60%">
<el-table-column prop="name" label="姓名" />
<el-table-column prop="amount1" label="数值1" />
<el-table-column prop="amount2" label="数值2" />
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData:[
{
name:'Tom',amount1:10,amount2:15},
{
name:'Tom',amount1:11,amount2:16},
{
name:'Jack',amount1:12,amount2:17},
{
name:'Andy',amount1:13,amount2:18},
{
name:'Andy',amount1:14,amount2:19}
]
};
},
methods: {
}
};
</script>
实例1:合并第一列的前两行
//合并方法
objectSpanMethod({
row, column, rowIndex, columnIndex }){
if(columnIndex==0){
//如果是第一行,就合并两行
if(rowIndex==0){
return {
rowspan:2,
colspan:1
}
}
}
}
可以看出是数据错列了。原因如下:
虽然第0行,让他合并了两行一列,但是第二行的那个tom是还存在的,所以导致错行。
正确的方式应该是第一行合并后,其余多出来的应该隐藏掉。隐藏单元格可以通过{rowspan:0,colspan:0}
来实现,表示不渲染(两个都等于0,或者某一个等于0都行,后面会用到这里)
//合并方法
objectSpanMethod({
row, column, rowIndex, columnIndex }) {
let _row = 2;
if (columnIndex == 0) {
//如果是第一行,就合并两行
if (rowIndex == 0) {
return {
rowspan: _row,
colspan: 1,
};
} else {
//其他行
//因为合并了前两行,第0行已经占两行了,第一行,应该隐藏,其他行正常显示
if (rowIndex < _row) {
return {
rowspan: 0,
colspan: 1,
};
}
}
}
},
实例2:第一列相同姓名的行合并
上面那个例子,实际用处不大,但是可以作为一个很好理解的例子。基于实例1,开始实现实例2 。
数据可以简化成 Tom Tom Jack Andy Andy,按照实例1,合并的行数应该是2,0,1,2,0(2表示合并两行,0表示要隐藏,依次类推),得到这几个数字就是我们需要处理的逻辑,具体逻辑如下:
//获取要合并的行数
getSpanNumber(data, prop) {
//data要处理的数组,prop要合并的属性,比如name
//数组的长度,有时候后台可能返回个null而不是[]
let length = Array.isArray(data) ? data.length : 0;
if (length > 0) {
//用于标识位置
let position = 0;
//用于对比的数据
let temp = data[0][prop];
//要返回的结果
let result = [1];
//假设数据是AABCC,我们的目标就是返回20120
for (let i = 1; i < length; i++) {
if (data[i][prop] == temp) {
//标识位置的数据加一
result[position] += 1;
//当前位置添0
result[i] = 0;
} else {
//不相同时,修改标识位置,该位置设为1,修改对比值
position = i;
result[i] = 1;
temp = data[i][prop];
}
}
//返回结果
return result;
} else {
return [0];
}
},
测试一下数据:
mounted() {
console.log("结果:", this.getSpanNumber(this.tableData,'name'));
},
实现上面的需求
<template>
<div>
<el-table :data="tableData" border style="width: 60%" :span-method="objectSpanMethod">
<el-table-column prop="name" label="姓名" />
<el-table-column prop="amount1" label="数值1" />
<el-table-column prop="amount2" label="数值2" />
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
name: "Tom", amount1: 10, amount2: 15 },
{
name: "Tom", amount1: 11, amount2: 16 },
{
name: "Jack", amount1: 12, amount2: 17 },
{
name: "Andy", amount1: 13, amount2: 18 },
{
name: "Andy", amount1: 14, amount2: 19 },
],
};
},
mounted() {
console.log("结果:", this.getSpanNumber(this.tableData, "name"));
},
methods: {
//合并方法
objectSpanMethod({
row, column, rowIndex, columnIndex }) {
if (columnIndex == 0) {
//合并相同的名字
let nameSpan = this.getSpanNumber(this.tableData, "name");
return {
rowspan: nameSpan[rowIndex],
colspan: 1,
};
}
},
//获取要合并的行数
getSpanNumber(data, prop) {
//data要处理的数组,prop要合并的属性,比如name
//数组的长度,有时候后台可能返回个null而不是[]
let length = Array.isArray(data) ? data.length : 0;
if (length > 0) {
//用于标识位置
let position = 0;
//用于对比的数据
let temp = data[0][prop];
//要返回的结果
let result = [1];
//假设数据是AABCC,我们的目标就是返回20120
for (let i = 1; i < length; i++) {
if (data[i][prop] == temp) {
//标识位置的数据加一
result[position] += 1;
//当前位置添0
result[i] = 0;
} else {
//不相同时,修改标识位置,该位置设为1,修改对比值
position = i;
result[i] = 1;
temp = data[i][prop];
}
}
//返回结果
return result;
} else {
return [0];
}
},
},
};
</script>
结果: