vxe-table 自定义表头合并:灵活合并任意列头
在实际项目中,默认的多级树形分组列头可能无法满足复杂报表的展示需求。vxe-table 提供了 show-custom-header 配置项,允许你完全自定义表头结构,实现任意行列的合并效果(类似 Excel 中的跨列居中、跨行合并)。
需要注意:启用自定义表头合并后,被合并的列将不支持拖拽调整列宽(因为合并后的列在视觉上不再是一列,而是多个列的集合)。此外,自定义合并的配置需要手动维护合并规则(mergeHeaderCells)。
参数
| 配置项 | 类型 | 说明 |
|---|---|---|
| showCustomHeader | Boolean | 开启自定义表头模式。默认为 false,此时表头为树形分组结构;设置为 true 后,表头完全由 mergeHeaderCells 和 columns 共同决定。 |
| mergeHeaderCells | Array | 合并规则数组,每个对象描述一个合并单元格的位置和跨度。格式:{ row: 0, col: 0, rowspan: 2, colspan: 1 }。 |
| columns | Array | 列定义。即使在自定义合并模式下,仍需定义所有基础列字段,供数据渲染使用。 |
原理:当 showCustomHeader: true 时,表头不再自动根据 columns 的 children 生成层级,而是完全依据 mergeHeaderCells 指定的合并规则来渲染。你需要为每一个基础列(叶子列)指定它在表头矩阵中的位置(row 和 col),并通过 rowspan / colspan 合并相邻单元格。
代码

<template>
<div>
<vxe-button @click="setMerge1">设置合并1</vxe-button>
<vxe-button @click="setMerge2">设置合并2</vxe-button>
<vxe-button status="success" @click="saveMergeData">获取合并规则</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showCustomHeader: true,
height: 400,
mergeHeaderCells: [
{ row: 0, col: 0, rowspan: 2, colspan: 1 },
{ row: 0, col: 1, rowspan: 2, colspan: 1 },
{ row: 0, col: 2, rowspan: 1, colspan: 2 },
{ row: 0, col: 4, rowspan: 1, colspan: 2 },
{ row: 1, col: 6, rowspan: 1, colspan: 2 },
{ row: 0, col: 8, rowspan: 2, colspan: 1 }
],
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name' },
{
title: 'Group1',
field: 'group1',
headerAlign: 'center',
children: [
{ field: 'sex', title: 'Sex' },
{ field: 'age', title: 'Age' }
]
},
{
field: 'group3',
title: 'Group3',
headerAlign: 'center',
children: [
{ field: 'attr5', title: 'Attr5' },
{ field: 'attr6', title: 'Attr6' }
]
},
{
field: 'group6',
title: 'Attr3',
children: [
{ field: 'attr3', title: 'Group8', headerAlign: 'center' }
]
},
{
field: 'group8',
title: 'Attr4',
children: [
{ field: 'attr4', title: 'Attr4' }
]
},
{ field: 'address', title: 'Address' }
],
data: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 46, attr3: 22, attr4: 100, attr5: 66, attr6: 86, address: 'Guangzhou' },
{ id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Shenzheng' },
{ id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 0, attr3: 22, attr4: 0, attr5: 0, attr6: 0, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Guangzhou' },
{ id: 10005, name: 'Test5', role: 'Test', sex: 'Women', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Shenzheng' },
{ id: 10006, name: 'Test6', role: 'Develop', sex: 'Man', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Guangzhou' },
{ id: 10007, name: 'Test7', role: 'Designer', sex: 'Women', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Guangzhou' },
{ id: 10008, name: 'Test8', role: 'Test', sex: 'Man', age: 0, attr3: 0, attr4: 0, attr5: 0, attr6: 0, address: 'Guangzhou' }
]
})
const setMerge1 = () => {
gridOptions.mergeHeaderCells = [
{ row: 0, col: 0, rowspan: 2, colspan: 1 },
{ row: 0, col: 1, rowspan: 2, colspan: 1 },
{ row: 0, col: 2, rowspan: 1, colspan: 2 },
{ row: 0, col: 4, rowspan: 1, colspan: 2 },
{ row: 1, col: 6, rowspan: 1, colspan: 2 },
{ row: 0, col: 8, rowspan: 2, colspan: 1 }
]
}
const setMerge2 = () => {
gridOptions.mergeHeaderCells = [
{ row: 0, col: 0, rowspan: 2, colspan: 1 },
{ row: 0, col: 1, rowspan: 2, colspan: 1 },
{ row: 0, col: 2, rowspan: 1, colspan: 4 },
{ row: 1, col: 6, rowspan: 1, colspan: 3 }
]
}
const saveMergeData = () => {
const $grid = gridRef.value
if ($grid) {
const mergeList = $grid.getMergeHeaderCells()
console.log(mergeList)
}
}
</script>

注意
| 注意事项 | 说明 |
|---|---|
| 列宽调整限制 | 被合并的列(即参与 colspan 的列)将无法通过拖拽调整列宽。如果需要调整列宽,请在未合并的列上进行,或通过代码动态设置列宽。 |
| 合并规则与列索引对应 | mergeHeaderCells 中的 col 索引指的是 columns 数组的索引(从0开始)。当有 type: 'seq' 或 type: 'checkbox' 等内置列时,这些列也占用一个索引位置。 |
| 行索引规则 | 合并的行索引 row 从0开始(第一行表头)。如果合并后表头最大行数为2,则有效行索引为0和1。超出范围会导致渲染异常。 |
| 必须保证所有基础列被覆盖 | 每一个叶子列(即实际绑定字段的列)在表头矩阵中都必须有对应的单元格,否则该列将没有表头文字。合并时可以通过 colspan 让多个列共享一个表头单元格。 |
| 动态切换合并规则 | 直接修改 mergeHeaderCells 会触发表头重新渲染,但不会影响已加载的数据。如果表格数据量大,频繁切换可能引起性能抖动,建议使用防抖或仅在必要时切换。 |
| 与列固定(fixed)的兼容 | 如果某些列设置了 fixed(左右固定),合并规则需要小心处理,避免将固定列与非固定列合并,否则可能导致样式错乱。 |
- vxe-table 的 showCustomHeader 和 mergeHeaderCells 提供了一种高度自由的自定义表头合并方案,适用于需要复杂表头布局的报表、数据展示等场景。主要优势包括:
- 完全自定义:不受内置树形分组限制,可以实现任意行列合并。
- 动态可切换:通过修改 mergeHeaderCells 即可实时改变表头结构。
- 与数据解耦:合并只影响表头展示,不影响数据行的渲染和绑定。

浙公网安备 33010602011771号