最近写项目时遇到了将表格前两列相同数据进行单元格合并,故以此分享一下表格合并的具体实现逻辑,如有更简单的方法可互相交流!!!
一.表格前两列进行合并
前提条件:第二列合并需在第一列合并的前提下才能进行合并,构建一个element plus表格,通过span-method方法进行表格列合并,先获取第一列合并后的span再进行第二列合并数据,只有相邻的单元格可合并。
ini
const tableData = ref([
{ category: '水果', subCategory: '热带', name: '芒果', type: '111' },
{ category: '水果', subCategory: '热带', name: '香蕉', type: '111' },
{ category: '水果', subCategory: '热带', name: '香蕉', type: '111' },
{ category: '水果', subCategory: '11', name: '苹果', type: '4' },
{ category: '水果', subCategory: '热带', name: '苹果', type: '5' },
{ category: '水果', subCategory: '热带', name: '胡萝卜', type: '6' },
{ category: '蔬菜', subCategory: '热带', name: '胡萝卜', type: '7' },
{ category: '蔬菜', subCategory: '11', name: '菠菜', type: '8' },
{ category: '蔬菜', subCategory: '白菜', name: '菠菜', type: '8' },
{ category: '蔬菜', subCategory: '白菜', name: '菠菜', type: '8' },
{ category: '蔬菜', subCategory: '热带', name: '菠菜', type: '8' },
]);
const mergeMap = computed(() => {
const map = [];
const data = tableData.value;
// 1. 第一列:合并相同的category
const col1 = Array(data.length).fill(1);
let i = 0;
while (i < data.length) {
const currentCategory = data[i].category;
let span = 1;
for (let j = i + 1; j < data.length; j++) {
if (data[j].category === currentCategory) {
span++;
} else {
break;
}
}
if (span > 1) {
col1[i] = span;
for (let k = i + 1; k < i + span; k++) {
col1[k] = 0;
}
}
i += span;
}
map.push(col1);
// 2. 第二列:在相同category下合并相同的subCategory
const col2 = Array(data.length).fill(1);
let row = 0;
while (row < data.length) {
// 找到当前category组
let categoryEnd = row + (col1[row] || 1);
// 在当前category组内处理subCategory
let j = row;
while (j < categoryEnd) {
const currentSubCategory = data[j].subCategory;
let span = 1;
for (let k = j + 1; k < categoryEnd; k++) {
if (data[k].subCategory === currentSubCategory) {
span++;
} else {
break;
}
}
if (span > 1) {
col2[j] = span;
for (let x = j + 1; x < j + span; x++) {
col2[x] = 0;
}
}
j += span;
}
row = categoryEnd;
}
map.push(col2);
// 3. 第三列:永远不合并,每行都显示
const col3 = Array(data.length).fill(1);
map.push(col3);
return map;
});
// 合并方法
const handleSpan = ({ rowIndex, columnIndex }) => {
if (columnIndex >= mergeMap.value.length) return { rowspan: 1, colspan: 1 };
const span = mergeMap.value[columnIndex][rowIndex];
return span === 0 ? { rowspan: 0, colspan: 0 } : { rowspan: span, colspan: 1 };
};
实现效果如下:

二.表格中所有列均可以合并,可以让最后一列不合并,以防两行数据合并成一行,效果不明显,具体代码实现如下:
ini
const tableData = ref([
{ category: '水果', subCategory: '热带', name: '芒果', type: '111' },
{ category: '水果', subCategory: '热带', name: '香蕉', type: '111' },
{ category: '水果', subCategory: '热带', name: '香蕉', type: '111' },
{ category: '水果', subCategory: '11', name: '苹果', type: '4' },
{ category: '水果', subCategory: '热带', name: '苹果', type: '5' },
{ category: '水果', subCategory: '热带', name: '胡萝卜', type: '6' },
{ category: '蔬菜', subCategory: '热带', name: '胡萝卜', type: '7' },
{ category: '蔬菜', subCategory: '热带', name: '菠菜', type: '8' },
]);

// 预处理合并信息
const mergeMap = computed(() => {
const map = [];
const keys = ['category', 'subCategory', 'name', 'type'];
// 为每一列计算合并信息
for (let col = 0; col < keys.length; col++) {
const currentCol = new Array(tableData.value.length).fill(1);
if (col === 0) {
// 第一列:直接合并相同值
let i = 0;
while (i < tableData.value.length) {
const currentValue = tableData.value[i][keys[col]];
let span = 1;
for (let j = i + 1; j < tableData.value.length; j++) {
if (tableData.value[j][keys[col]] === currentValue) {
span++;
} else {
break;
}
}
if (span > 1) {
currentCol[i] = span;
for (let k = i + 1; k < i + span; k++) {
currentCol[k] = 0;
}
}
i += span;
}
} else {
// 后续列:在前一列合并的基础上合并相同值
let i = 0;
while (i < tableData.value.length) {
// 找到前一列的合并组
let groupEnd = i;
if (map[col-1][i] > 1) {
// 前一列有合并
groupEnd = i + map[col-1][i];
} else {
// 前一列没有合并
groupEnd = i + 1;
}
// 在当前组内处理当前列的合并
let j = i;
while (j < groupEnd) {
const currentValue = tableData.value[j][keys[col]];
let span = 1;
for (let k = j + 1; k < groupEnd; k++) {
if (tableData.value[k][keys[col]] === currentValue) {
span++;
} else {
break;
}
}
if (span > 1) {
currentCol[j] = span;
for (let x = j + 1; x < j + span; x++) {
currentCol[x] = 0;
}
}
j += span;
}
i = groupEnd;
}
}
map.push(currentCol);
}
return map;
});
// 合并方法
const handleSpan = ({ rowIndex, columnIndex }) => {
if (columnIndex >= mergeMap.value.length) return { rowspan: 1, colspan: 1 };
const span = mergeMap.value[columnIndex][rowIndex];
return span === 0 ? { rowspan: 0, colspan: 0 } : { rowspan: span, colspan: 1 };
};
结束语
如果你也遇到了相同的需求,希望可以帮到你!