需求:将查询出来的表格数据按照值相同的原则进行合并,行和列都要合并。
效果:
技术分析:
1、表格插件使用 Element-plush 提供的组件 el-table 实现。
2、 el-table 本身就提供了一个 span-method tabel 属性供用户实现单元格合并的扩展。
3、span-method 接收一个函数,这个函数需用户自己实现,并需要返回一个二维数组或者对象。
4、el-table 在渲染每一个单元格的时候,都会调用这个函数获取对当前单元格合并情况,并根据获取到的合并情况进行渲染,并且调用的规律是一行一行的调用,例如:在渲染第一行的时候会将这一行上的所有的列处理完成之后才会处理第二行,第二行的处理逻辑也是相似的。
思路分析:
1、在获取到数据的之后,首先根据数据情况判断单元格合并情况,即:生成需要合并行的二维数组情况,生成需要合并列的二维数组情况。
2、在 span-method 调用的函数中,每次根据函数返回来的 rowIndex 和 columnIndex 就可以确定对应的单元格的合并情况。
技术实现:
1、数据获取到之后,调用 handleSpanData 函数生成单元格合并情况,span-method 接收 spanObjectMethod 函数渲染单元格。
① needSpanColumn:存储每一列对应的每一个单元格的合并情况。例如:{0: [1, 2, 0]} 表明第一行数据的第一列不需要合并;第一行数据的第二列需要合并,并向后合并两列;第一行数据的第三列不需要合并,并且隐藏显示。
② needSpanRow:存储每一列对应的每一个单元格的合并情况。例如:{0: [2]} 、{1: [0]} 表明第一列数据的第一行对应的单元格需要合并,并向后下合并两行,并且第一列数据的第二行对应的单元格隐藏显示。
const handleSpanData = () => {
const dataDetails = tableData || [];
const needSpanColumn = {};
const columns = tableOption.map((item) => item.prop);
// 行 列 -> 横向比较,合并的是列,代表是当前行需要合并的单元格数量
dataDetails.forEach((row, rowIndex) => {
let rowFlag = -1;
needSpanColumn[rowIndex] = [1];
columns.forEach((column, columnIndex) => {
if (columnIndex === 0) {
return;
}
if (rowFlag === -1) {
rowFlag = columnIndex - 1;
}
if (row[column] === row[columns[columnIndex - 1]]) {
needSpanColumn[rowIndex][rowFlag] += 1;
needSpanColumn[rowIndex].push(0);
return;
}
needSpanColumn[rowIndex].push(1);
rowFlag = -1;
});
});
console.table(needSpanColumn);
// 列 行 -> 竖向比较, 代表是当前列需要合并的单行数
const needSpanRow = {};
columns.forEach((column, columnIndex) => {
let columnFlag = -1;
needSpanRow[columnIndex] = [1];
dataDetails.forEach((row, rowIndex) => {
if (rowIndex === 0) {
return;
}
if (columnFlag === -1) {
columnFlag = rowIndex - 1;
}
if (row[column] === dataDetails[rowIndex - 1][column]) {
needSpanRow[columnIndex][columnFlag] += 1;
needSpanRow[columnIndex].push(0);
return;
}
needSpanRow[columnIndex].push(1);
columnFlag = -1;
});
});
console.table(needSpanRow);
return { needSpanColumn, needSpanRow };
};
const spanObjectMethod = ({ row, column, rowIndex, columnIndex }) => {
console.info('🚀 ~ file:TableSpan.vue method:spanObjectMethod line:73 -----', rowIndex, columnIndex);
return [needSpanRow1[columnIndex][rowIndex], needSpanColumn1[rowIndex][columnIndex]];
};
测试数据验证:
const tableData: any[] = [
{"item1": "1","item2": "3","item3": "3","item4": "3","item5": "4"},
{"item1": "2","item2": "5","item3": "5","item4": "5","item5": "4"},
{"item1": "3","item2": "3","item3": "2","item4": "4","item5": "5"},
{"item1": "4","item2": "9","item3": "7","item4": "4","item5": "5"},
{"item1": "5","item2": "6","item3": "7","item4": "8","item5": "9"}
];