项目最近有一个新需求,在添加表格内容时需要判断单元格内容。把同列相同数据合并成一个单元格。当时想着挺简单的,但等到自己实际操作起来就知道难了。
我最开始是记得element的表格是有自带合并单元格功能的。
有明确的方法指引该如何进行单元格合并。这时候就把代码cv下来,自己开始操作
但我做的是一个带编辑内容的表格。中途就出现了很多问题。但逻辑还是一样的,还好只做列的合并,工作量就小了很多。接下来展示一下我的思路
// 合并指定单元格
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// rowIndex 列(竖)序 columnIndex 行(横)序
if (columnIndex < 3) { // 只合并前三列的数据
// 判断同列下一条是否有需要合并的数据
const rowspan = this.getColspan(rowIndex, columnIndex);
// 判断同列上一条数据是否与自身相同
const topspan = this.getColspan(rowIndex - 1, columnIndex);
if (rowspan > 1) { // 代表下列有可合并的数据、
if (topspan > 1) { // 上一条已经合并
return {
rowspan: 0,
colspan: 0
};
} else {
return {
rowspan: rowspan,
colspan: 1
};
}
} else {
// 返回0就代表隐藏该内容 1代表不合并不隐藏
// console.log(rowIndex, columnIndex, topspan)
if (topspan > 1 || rowspan > 1) { // 如果上一条数据或下一条数据与自身相 同 则隐藏当前数据
return {
rowspan: 0,
colspan: 0
};
} else {
return {
rowspan: 1,
colspan: 1
};
}
}
}
},
// 可以扩展到其他列的合并逻辑
getColspan(rowIndex, columnIndex) {
if (rowIndex < 0) { // 第一条数据 上一条不存在 直接跳过
return;
}
let rowspan = 1;
const list = this.tableList;
for (let i = rowIndex + 1; i < list.length; i++) {
if (columnIndex > 0) { // 需要判断第一列是否在合并状态 然后再处理后续列
if (list[rowIndex][Object.keys(list[rowIndex])[columnIndex]] === list[i][Object.keys(list[i])[columnIndex]] && list[rowIndex][Object.keys(list[rowIndex])[0]] === list[i][Object.keys(list[i])[0]]) {
rowspan++;
} else {
break;
}
} else {
// 数组的对比需要单独处理
if (list[rowIndex][Object.keys(list[rowIndex])[columnIndex]].constructor === Array && list[i][Object.keys(list[i])[columnIndex]] === Array && this.isArrEqual1(list[rowIndex][Object.keys(list[rowIndex])[columnIndex]], list[i][Object.keys(list[i])[columnIndex]])) {
rowspan++;
} else {
if (list[rowIndex][Object.keys(list[rowIndex])[columnIndex]] === list[i][Object.keys(list[i])[columnIndex]]) {
rowspan++;
} else {
break;
}
}
}
}
return rowspan;
},
// 判断两个数组是否相同
isArrEqual1(arr1, arr2) {
if (arr1.length !== arr2.length) {
return false;
}
return arr1.every((v, i) => v === arr2[i]);
}
因为项目需求是在第一列已合并的条件下再判断后续列是否继续合并,并且只做前三行的判断。所以做了单独处理,里面还出现了数据内容可能是数组的情况。如果有其他的数据类型,可以根据我做的判断来进行更改。
最后展示一下实现后的效果图
中途还碰到一个问题,因为是可编辑的表单,在新增数组内容的时候会出现合并错乱的问题。经过仔细排查,我发现在添加新数据的时候需要把前三列的数据做一个对应,例如我的列表第一列是区域,第二第三是泡重比开始结束。那么在新增数据的时候就需要这样写
const dataObj = {
region: 区域信息,
startBubbleRatio: 泡重比开始,
endBubbleRatio: 泡重比结束,
startWeightRange: 0,
endWeightRange: 0,
firstWeight: 0,
firstWeightPrice: 0,
additionalWeight: 0,
additionalWeightPrice: 0
};
每一列的数据添加都需要对应表格的单位,不然就会出现合并错乱的问题。如果不是可编辑的内容就不用担心出现这种问题了。
问题接着就来了,在第一列合并的情况下,后续添加的数据要适配对应的位置,例如效果图中北京市再添加一条1-2泡重比区间的数据,就需要放到上门去,和原本的列合并起来。
handleAddLable(data, index) {
// 直接在操作方法的时候把当前下标和所合并的行数都拿到手
this.selectIndex = index;
// 合并了几行
this.ordersNum = this.getColspan(data.$index, 0);
this.$refs.addWeight.show(this.detailDTOs);
},
if (this.ordersNum > 1) {
// 在合并格里添加数据 先截取合并内容
const arr = this.tableList.slice(this.selectIndex, this.selectIndex + this.ordersNum);
// 将合并内容截取后,再根据下标判断添加的位置
const index = arr.map(item => item.endBubbleRatio).lastIndexOf(data.endBubbleRatio);
if (index === -1) {
this.tableList.splice(this.selectIndex + this.ordersNum, 0, dataObj);
} else {
this.tableList.splice(this.selectIndex + index, 0, dataObj);
}
} else {
this.tableList.splice(this.selectIndex, 0, dataObj);
}
后续如果有其他问题会继续更新的