两种方法,各取所需,最后的效果图是不同的
第一种
methods: {
getAllInfo() {
getAllInfos(this.queryParams).then(response => {
// console.log(response.rows)
this.loading = false//遮罩层
let dataArr = response.rows//后端传输过来的数据
let dataSolve = this.mergeTableRow(dataArr, ["合并字段一", "合并字段二", "合并字段三", "合并字段四"...]);
this.tableData = dataSolve;
}).catch(err => {
console.log(err)
})
},
// 合并表格
mergeTableRow(data, merge) {
if (!merge || merge.length === 0) {
return data;
}
merge.forEach((m) => {
const mList = {};
let spliceLocation = merge.indexOf(m)
data = data.map((v, index) => {
const rowVal = v[m];
if (mList[rowVal] && mList[rowVal].newIndex === index) {
// flag为true的时候代表当前值的前者与上一个值相等
/*
只有当当前merge之前的所有merge的值的当前index等于index-1 才允许当前merge合并
*/
let flag = false;
let mergeSolve = merge.slice(0, spliceLocation);
mergeSolve.slice(0, spliceLocation).forEach(mergeItem => {
if (data[index][mergeItem] == data[index - 1][mergeItem]) {
flag = true
}
})
if (m == merge[0]) {
flag = true;
}
if (flag) {
mList[rowVal]["num"]++;
mList[rowVal]["newIndex"]++;
data[mList[rowVal]["index"]][m + "-span"].rowspan++;
v[m + "-span"] = {
rowspan: 0,
colspan: 0,
};
} else {
mList[rowVal] = {
num: 1,
index: index,
newIndex: index + 1,
};
v[m + "-span"] = {
rowspan: 1,
colspan: 1,
};
}
} else {
mList[rowVal] = {
num: 1,
index: index,
newIndex: index + 1,
};
v[m + "-span"] = {
rowspan: 1,
colspan: 1,
};
}
return v;
});
});
return data;
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
const span = column["property"] + "-span";
if (row[span]) {
return row[span];
}
},
},
第二种(比第一种麻烦),因为每次合并都需要swich去匹配的,这时如果已经写好的字段顺序发生改变,case的值也就需要我们去改变,合并的字段少还好,如果字段多的话就会很麻烦,所以还是推荐第一种
methods: {
getAllInfo() {
getAllInfos(this.queryParams).then(response => {
// console.log(response.rows)
this.loading = false
this.tableData = response.rows
}).catch(err => {
console.log(err)
})
},
mergeCol(id, rowIndex) { // 合并单元格
// id:属性名
// rowIndex:行索引值
let idName = this.tableData[rowIndex][id] // 获取当前单元格的值
if (rowIndex > 0) { // 判断是不是第一行
// eslint-disable-next-line eqeqeq
if (this.tableData[rowIndex][id] != this.tableData[rowIndex - 1][id]) { // 先判断当前单元格的值是不是和上一行的值相等
let i = rowIndex;
let num = 0 // 定义一个变量i,用于记录行索引值并进行循环,num用于计数
while (i < this.tableData.length) { // 当索引值小于table的数组长度时,循环执行
if (this.tableData[i][id] === idName) { // 判断循环的单元格的值是不是和当前行的值相等
i++ // 如果相等,则索引值加1
num++ // 合并的num计数加1
} else {
i = this.tableData.length // 如果不相等,将索引值设置为table的数组长度,跳出循环
}
}
return {
rowspan: num, // 最终将合并的行数返回
colspan: 1
}
} else {
return {
rowspan: 0, // 如果相等,则将rowspan设置为0
colspan: 1
}
}
} else { // 如果是第一行,则直接返回
let i = rowIndex;
let num = 0
while (i < this.tableData.length) { // 当索引值小于table的数组长度时,循环执行
if (this.tableData[i][id] === idName) {
i++
num++
} else {
i = this.tableData.length
}
}
return {
rowspan: num,
colspan: 1
}
}
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) { // 合并单元格
// console.log(columnIndex)
switch (columnIndex) { // 将列索引作为判断值
// 通过传递不同的列索引和需要合并的属性名,可以实现不同列的合并
case 0:
return this.mergeCol('字段一', rowIndex)
break;
case 1:
return this.mergeCol('字段二', rowIndex)
break;
case 2:
return this.mergeCol('字段三', rowIndex)
break;
default:
break;
}
},
}
两种效果图对比
第一种
第二种