最近有一个产品需求是需要一个有合并单元格场景的表格展示数据,但是element-ui合并单元格作为一个前端菜鸟也是没有用过,所以只能抱着探索的心态是看了下表格的知识。首先看下产品的原型图
从图中可以看出时间和支付渠道为apple 和总计的属性需要合并行,其实可以兼容成所有的渠道都可以合并,如果看了element-ui 关于table 的使用的话,应该清楚单元格合并需要的两个元素,一个是合并的列的索引一个是需要合并的行数(几行合并为一行)还有就是从哪一行开始合并。
从图中可以看到我们需要合并的哪一列是明确的,那么难点就是如何确定从哪一行开始合并以及合并多少行呢。
tableData: [
{
date: "2021/08/23",
chanel: "微信",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "人民币",
due: 23,
final_get: 1000
},
{
date: "2021/08/23",
chanel: "apple",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "人民币",
due: 23,
final_get: 1000
},
{
date: "2021/08/23",
chanel: "apple",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "美元",
due: 23,
final_get: 1000
},
{
date: "2021/08/23",
chanel: "总计",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "人民币",
due: 23,
final_get: 1000
},
{
date: "2021/08/23",
chanel: "总计",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "美元",
due: 23,
final_get: 1000
},
{
date: "2021/08/24",
chanel: "支付宝",
diamond: 100,
should_pay: 100,
real_pay: 100,
trade_type: "人民币",
due: 23,
final_get: 1000
},
{
date: "2021/08/24",
chanel: "总计",
diamond: 99,
should_pay: 100,
real_pay: 100,
trade_type: "美元",
due: 23,
final_get: 1000
}
]
上面是我造的假数据,在后续的操作中会添加一些辅助字段在里面
let temp_data_list = [];
for (let j = 0; j < this.tableData.length; j++) {
if (j !== 0) {
if (this.tableData[j].date !== this.tableData[j - 1].date) {
this.tableData[j].isCanMerageDate = true;
let info = {
date: this.tableData[j].date,
dateLength: 1
};
temp_data_list.push(info);
} else {
//两条date 相同则数量加1
for (let i = 0; i < temp_data_list.length; i++) {
if (temp_data_list[i].date === this.tableData[j].date) {
temp_data_list[i].dateLength += 1;
}
}
}
if (this.tableData[j].chanel !== this.tableData[j - 1].chanel) {
this.tableData[j].isCanMerageChanel = true;
let chanel_info = {
chanel: this.tableData[j].chanel,
date: this.tableData[j].date,
chanelLength: 1
};
temp_data_list.push(chanel_info);
} else {
for (let i = 0; i < temp_data_list.length; i++) {
if (temp_data_list[i].chanel === this.tableData[j].chanel) {
temp_data_list[i].chanelLength += 1;
}
}
}
} else {
this.tableData[0].isCanMerageDate = true;
this.tableData[0].isCanMerageChanel = true;
let info = {
date: this.tableData[0].date,
dateLength: 1,
chanelLength: 1,
chanel: this.tableData[0].chanel
};
temp_data_list.push(info);
}
}
temp_data_list 是整合后的符合条件的信息的集合
第一条数据也就是j=0 时候,第一条的日期,和渠道一定是可以向下合并的,只不过合并的行数有可能是1。所以此时的渠道和日期 isCanMerageDate和isCanMerageChanel 都为true 即 此条可以向下合并行
当j>0 的时候,如果前后两条数据的日期不一致,那么需要把后一条的时间保存,并且可以合并的日期长度记为1 ;
当前后两条数据的日期一致的时候,需要遍历已经保存的合并消息,当两条日期相当的时候把合并长度加1。
同理渠道的信息获取和日期的一致
当操作完这个列表的时候我们看下此时的temp_data_list
我们已经拿到了我们想要的数据集合,结下来就需要把对应的合并信息补充到 tableData 里,其实主要补充的是合并的长度
for (let i = 0; i < temp_data_list.length; i++) {
for (let j = 0; j < this.tableData.length; j++) {
if (
this.tableData[j].isCanMerageDate &&
temp_data_list[i].date === this.tableData[j].date &&
!isNaN(temp_data_list[i].dateLength)
) {
this.tableData[j].date_length = temp_data_list[i].dateLength;
}
if (
this.tableData[j].isCanMerageChanel &&
temp_data_list[i].chanel === this.tableData[j].chanel &&
temp_data_list[i].date === this.tableData[j].date
) {
this.tableData[j].chanel_length = temp_data_list[i].chanelLength;
}
}
}
新的tabledata 的数据结构大体是这个样子
最后我们需要绑定自定义的合并方法
<el-table
:data="tableData"
border
:span-method="objectSpanMethod"
style="width: 100%"
>
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
return {
rowspan: row.isCanMerageDate?row.date_length:0,
colspan: 1
};
} else if (columnIndex === 1) {
return {
rowspan: row.isCanMerageChanel?row.chanel_length:0,
colspan: 1
};
}
}
最后看下运行效果
大功告成