在开发数据表格时,经常遇到需要将数据按类别分组展示的需求。通常我们会想到树形表格或展开行,但有时业务要求一个扁平的分类样式——即在表格顶部直接展示分组标题,下方列出该分组内的明细数据,并且分组标题可以横跨整行。本文介绍一种巧妙的实现方式:插入分类行 + 单元格合并,以模拟类似“分组报表”的视觉效果。
实现思路
1.数据预处理:在原始数据中插入分类行(type: 'group'),并给每个分类行设定 level(层级)、count(数量)等元信息。 2.合并单元格:利用 vxe-table 的 mergeCells 配置,让分类行的第一列(或需要的列)跨越所有列(或指定列范围),从而占满整行。 3.自定义渲染:通过列模板(slots)区分普通行与分类行,为分类行渲染成醒目的标签样式,包含分类名称和数量统计。
这种方法避免了复杂的树递归和展开/折叠逻辑,非常适合静态分组或轻量级分类展示。
代码
分类行以带背景色的标签展示,并自动合并所有列,视觉上像是一个分组标题
<template>
<div>
<vxe-grid v-bind="gridOptions">
<template #group_name="{ row }">
<span v-if="row.type === 'group'">
<vxe-tag :status="row.level === 1 ? 'success' : 'warning'" class="group-name">{{ row.name }}</vxe-tag>
<span class="group-count">数量:{{ row.count }}</span>
</span>
<span v-else>{{ row.seq }}</span>
</template>
</vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
mergeCells: [
{ row: 0, col: 0, rowspan: 1, colspan: 5 },
{ row: 2, col: 0, rowspan: 1, colspan: 5 }
],
columns: [
{ field: 'seq', title: '序号', width: 70, slots: { default: 'group_name' } },
{ field: 'name', title: 'Name' },
{ field: 'sex', title: 'Sex' },
{ field: 'age', title: 'Age' },
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: 10000001, name: '销售冠军', role: '', sex: '', age: 0, address: '', count: 1, type: 'group', level: 1, seq: '' },
{ id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc', seq: '1' },
{ id: 10000002, name: '普通销售', role: '', sex: '', age: 0, address: '', count: 3, type: 'group', level: 2, seq: '' },
{ id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou', seq: '2' },
{ id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai', seq: '3' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai', seq: '4' }
]
})
</script>
<style lang="scss" scoped>
.group-name {
padding: 0 8px;
}
.group-count {
padding-left: 8px;
}
</style>
1.数据构造:分类行与明细行混合
- 分类行必须包含 type: 'group' 标志,用于模板区分渲染逻辑。
- count 字段用于展示该分类下的记录条数。
- level 字段可以控制标签颜色(如一级分类绿色,二级分类橙色)。
- 明细行中的 seq 用于显示普通序号;分类行的 seq 为空字符串。
2.单元格合并配置
- mergeCells 数组定义了哪些单元格需要合并。
- 每个对象包含 row(行索引)、col(起始列索引)、rowspan(跨行数)、colspan(跨列数)。
- 分类行都在第0列开始合并覆盖所有5列,实现“一整块”的视觉效果。
- 行索引与 data 数组的顺序一一对应,插入分类行后索引会变化,需要手动计算或通过动态方法生成(也可通过计算属性自动生成合并配置)。
3.自定义模板渲染
- 通过 slots.default 指定自定义名字 group_name,在模板中用 #group_name 接收。
- 根据 row.type 判断是否为分类行,分别渲染标签或普通序号。
动态生成合并配置的进阶方法
当数据量较大或分类行位置不确定时,可以动态生成 mergeCells:
function buildMergeCells(data) {
const merges = []
data.forEach((item, idx) => {
if (item.type === 'group') {
merges.push({ row: idx, col: 0, rowspan: 1, colspan: 5 })
}
})
return merges
}
将此函数计算的结果赋值给 gridOptions.mergeCells,并确保数据变化时重新生成。