记一个 Table 跨行转换算法
源数据格式
js
[
[{ value: "一级" }, { value: "二级1" }, { value: "三级1" }],
[{ value: "一级" }, { value: "二级1" }, { value: "三级2" }],
[{ value: "一级" }, { value: "二级2" }, { value: "三级3" }],
];
HTML 模板
html
<table>
<tr v-for="(row, rowIndex) in computedData" :key="rowIndex">
<td v-for="(col, colIndex) in row" :rowspan="col.rowspan" :key="colIndex">{{ col.value }}</td>
</tr>
</table>
目标格式
js
// computedData
[
[
{ rowspan: 3, value: "一级" },
{ rowspan: 2, value: "二级1" },
{ rowspan: 1, value: "三级1" },
],
[{ rowspan: 1, value: "三级2" }],
[
{ rowspan: 1, value: "二级2" },
{ rowspan: 1, value: "三级3" },
],
];
难点解析
由于 table 跨行,会导致下一行的 td 不需要遍历,比如第一行的列跨到了第二行,那么第二行的列就不需要遍历。
所以 computedData 的 length 为 3、1、2
暂时没有特别好的办法,我所用的方式是生成 result 的时候,查找 result 中是否出现过相同值的单元格,如果出现,就 rowspan++
,如果没有出现,则 push 进数组。
转换算法
js
function getRowSpan(inputData, rowIndex, colIndex, valueKeyName) {
let n = 1;
while (
inputData[rowIndex + n] &&
inputData[rowIndex + n][colIndex][valueKeyName] === inputData[rowIndex][colIndex][valueKeyName]
) {
n++;
}
return n;
}
function isNeedShow(inputData, rowIndex, colIndex, valueKeyName) {
const prev = inputData[rowIndex - 1];
const current = inputData[rowIndex];
if (prev && current && prev[colIndex][valueKeyName] === current[colIndex][valueKeyName]) {
return false;
} else {
return true;
}
}
export function transformRowSpan(inputData, valueKeyName) {
const result = [];
inputData.forEach((row, rowIndex) => {
const computedRow = [];
row.forEach((col, colIndex) => {
if (isNeedShow(inputData, rowIndex, colIndex, valueKeyName)) {
const computedCol = { ...col };
computedCol.rowspan = getRowSpan(inputData, rowIndex, colIndex, valueKeyName) || 1;
computedRow.push(computedCol);
}
});
result.push(computedRow);
});
return result;
}