代码分析及 customCell 的使用详解
在这个代码片段中,customCell 是 Ant Design Vue 的 Table 组件中的一个功能,用于自定义单元格的属性(如 rowSpan 和 colSpan),以实现行、列的合并。下面是关于这段代码的详细分解:
customCell 的作用
customCell 函数允许我们为表格的每一列定义自定义的单元格属性。通过返回的对象,可以控制:
colSpan:决定该单元格是否横跨多列,0表示不渲染该单元格。rowSpan:决定该单元格是否跨多行,0表示该单元格和上一个单元格合并。
customCell 的代码逻辑
customCell: (_, index) => {
if (index === 2) {
return { rowSpan: 2 }; // 合并当前单元格和下一行的单元格(跨两行)
}
if (index === 3) {
return { rowSpan: 0 }; // 当前单元格与上一行的单元格合并,不再渲染
}
if (index === 4) {
return { colSpan: 0 }; // 当前单元格被合并到别的列,不再渲染
}
}
1. index === 2
if (index === 2) {
return { rowSpan: 2 };
}
- 解释:在
index === 2时,当前单元格将设置rowSpan: 2,表示该单元格会纵向合并当前行和下一行的同一列的单元格。 - 效果:这意味着 第3行的“Home phone”列会占据第3、4两行。
2. index === 3
if (index === 3) {
return { rowSpan: 0 };
}
- 解释:在
index === 3时,当前单元格将设置rowSpan: 0,表示该单元格与**前一行(index 2)**的单元格合并,并不会单独渲染。 - 效果:这使得第4行的“Home phone”列与第3行的单元格合并为一个。
3. index === 4
if (index === 4) {
return { colSpan: 0 };
}
- 解释:在
index === 4时,当前单元格的colSpan设置为0,表示该单元格不需要单独渲染,它会被横向合并到其他单元格中。 - 效果:这会导致第5行的“Home phone”列不再显示,整个单元格被隐藏或合并。
示例效果
- 第3行:
"Home phone"列会跨第3、4行。 - 第4行:
"Home phone"列的单元格与第3行的合并,因此不再显示单独的单元格。 - 第5行:
"Home phone"列的单元格不会渲染,因为其colSpan为0。
为什么需要 rowSpan 和 colSpan?
- 使用
rowSpan可以合并垂直方向的单元格,使其展示成一个整体。 - 使用
colSpan可以合并水平方向的单元格,隐藏不必要的重复信息。
通过这种方式,可以让表格看起来更加简洁,避免重复信息。像这种“合并单元格”的设计在需要分组显示数据时非常常见。
总结
customCell 函数通过返回 { rowSpan, colSpan } 控制单元格的渲染与合并。
- 如果某个单元格已经被其他单元格合并,则通过设置
rowSpan: 0或colSpan: 0隐藏它。 - 当
rowSpan > 1时,单元格会跨多行,节省空间。
你可以根据需求动态控制单元格的合并,提升表格的可读性。
如果你希望在 dataIndex = 'storageAssignment' 这一列进行合并,并且在合并后的单元格中间显示一个总和,可以通过设置 rowSpan 来合并行,同时动态计算合并后的总和,并在合并后的单元格内显示。
实现步骤
- 根据
storageAssignment列的值进行分组,合并相同值的行。 - 合并后的单元格中显示总和(例如对其他列的数值求和)。
- 设置
rowSpan和rowSpan: 0以控制单元格合并。
代码实现
代码结构
<template>
<a-table :columns="columns" :data-source="data" bordered>
<template #bodyCell="{ column, text, record, index }">
<template v-if="column.dataIndex === 'storageAssignment'">
<span v-if="getRowSpan(index) > 0">
{{ text }} - 总和: {{ getSum(record.storageAssignment) }}
</span>
</template>
</template>
</a-table>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import type { TableColumnType } from 'ant-design-vue';
// 数据示例
const data = [
{ key: '1', storageAssignment: 'A', quantity: 10 },
{ key: '2', storageAssignment: 'A', quantity: 20 },
{ key: '3', storageAssignment: 'B', quantity: 15 },
{ key: '4', storageAssignment: 'B', quantity: 25 },
{ key: '5', storageAssignment: 'C', quantity: 30 },
];
export default defineComponent({
setup() {
const dataSource = ref(data);
// 获取 `storageAssignment` 列的合并行数
const getRowSpan = (index: number) => {
const current = dataSource.value[index];
const previous = dataSource.value[index - 1];
// 如果是第一行或者值与上一行不同,则显示该组的行数
if (!previous || current.storageAssignment !== previous.storageAssignment) {
return dataSource.value.filter(
(item) => item.storageAssignment === current.storageAssignment
).length;
}
// 否则设置为 0(隐藏当前单元格)
return 0;
};
// 计算 `storageAssignment` 的总和
const getSum = (assignment: string) => {
return dataSource.value
.filter((item) => item.storageAssignment === assignment)
.reduce((sum, item) => sum + item.quantity, 0);
};
const columns: TableColumnType[] = [
{
title: 'Storage Assignment',
dataIndex: 'storageAssignment',
customCell: (_, index) => ({ rowSpan: getRowSpan(index) }),
},
{
title: 'Quantity',
dataIndex: 'quantity',
},
];
return {
data: dataSource,
columns,
getRowSpan,
getSum,
};
},
});
</script>
详细解释
-
合并逻辑:
getRowSpan函数- 遍历表格的每一行,如果某行的
storageAssignment与上一行不同,则计算该组的行数并返回该值作为rowSpan。 - 如果该单元格应该与上一行合并,则返回
0隐藏该单元格。
const getRowSpan = (index: number) => { const current = dataSource.value[index]; const previous = dataSource.value[index - 1]; if (!previous || current.storageAssignment !== previous.storageAssignment) { return dataSource.value.filter( (item) => item.storageAssignment === current.storageAssignment ).length; } return 0; }; - 遍历表格的每一行,如果某行的
-
求总和:
getSum函数- 遍历所有相同
storageAssignment的数据,并累加quantity值。
const getSum = (assignment: string) => { return dataSource.value .filter((item) => item.storageAssignment === assignment) .reduce((sum, item) => sum + item.quantity, 0); }; - 遍历所有相同
-
合并单元格并显示总和
- 在合并后的单元格内,通过
{{ text }} - 总和: {{ getSum(record.storageAssignment) }}显示当前分组的总和。
- 在合并后的单元格内,通过
效果
- 相同的
storageAssignment值的行会合并,并且在合并后的单元格中间显示分组的总和。 - 例如:
A - 总和: 30 B - 总和: 40 C - 总和: 30
总结
这段代码实现了:
- 按照
storageAssignment列的值进行分组并合并相同单元格。 - 在合并后的单元格内显示该分组的总和。
这种方法在处理类似库存管理或仓储分配的表格时非常实用。你还可以根据需要对数据源和样式进行进一步的定制。