使用 vxe-table 实现分类展示样式(非树结构/非展开行)

0 阅读3分钟

在开发数据表格时,经常遇到需要将数据按类别分组展示的需求。通常我们会想到树形表格或展开行,但有时业务要求一个扁平的分类样式——即在表格顶部直接展示分组标题,下方列出该分组内的明细数据,并且分组标题可以横跨整行。本文介绍一种巧妙的实现方式:插入分类行 + 单元格合并,以模拟类似“分组报表”的视觉效果。

实现思路

1.数据预处理:在原始数据中插入分类行(type: 'group'),并给每个分类行设定 level(层级)、count(数量)等元信息。 2.合并单元格:利用 vxe-table 的 mergeCells 配置,让分类行的第一列(或需要的列)跨越所有列(或指定列范围),从而占满整行。 3.自定义渲染:通过列模板(slots)区分普通行与分类行,为分类行渲染成醒目的标签样式,包含分类名称和数量统计。

这种方法避免了复杂的树递归和展开/折叠逻辑,非常适合静态分组或轻量级分类展示。

代码

分类行以带背景色的标签展示,并自动合并所有列,视觉上像是一个分组标题

image

<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,并确保数据变化时重新生成。

vxetable.cn