
本文介绍使用 Tabulator 的 rowFormatter 回调函数,通过原生 DOM 操作动态创建跨多列的合并单元格行,适用于 TypeScript 项目,无需计算逻辑,支持任意自定义内容渲染。
本文介绍使用 tabulator 的 `rowformatter` 回调函数,通过原生 dom 操作动态创建跨多列的合并单元格行,适用于 typescript 项目,无需计算逻辑,支持任意自定义内容渲染。
在 Tabulator 中,原生不支持单行内某单元格跨列(类似 HTML <td colspan="3">)的声明式配置,但可通过 <code>rowFormatter 函数对特定行进行底层 DOM 重构,实现视觉与语义上的列合并效果。该方案灵活、可控,特别适合需动态插入汇总行、分组标题、说明性横幅等场景。
✅ 核心实现思路
rowFormatter 在每行渲染完成后被调用,接收 RowComponent 实例。我们可获取其 DOM 元素(row.getElement()),提取子节点(即各列 <div class="tabulator-cell">),手动合并前 N 个单元格为一个宽容器,并保留其余列不变。<blockquote>
<p>⚠️ 注意事项: </p>
<ul>
<li>
<strong>列宽必须固定或禁用调整</strong>:因合并依赖 <code>style.width 计算,若列可拖拽调整(resizable: true),宽度值可能为 auto 或未生效,导致合并错位。建议对参与合并的列显式设置 resizable: false 及 width。
fitColumns 布局下宽度为动态计算值,建议改用 fitData 或 fitDataTable 并配合固定列宽以确保稳定性。 ? TypeScript 示例代码
以下为完整可运行的 TypeScript 片段(兼容 Tabulator v5.5+):
import { Tabulator, RowComponent } from 'tabulator-tables';
const tableData = [
{ id: 1, name: 'Billy Bob', age: '23', gender: 'male', height: 1, col: 'red', dob: '25/03/2000' },
{ id: 2, name: 'Mary May', age: '41', gender: 'female', height: 2, col: 'blue', dob: '14/05/1982' },
{ id: 3, name: 'Margret Marmajuke', age: '30', gender: 'female', height: 5, col: 'yellow', dob: '31/01/1993' }
];
const table = new Tabulator('#table', {
layout: 'fitData', // 推荐替代 fitColumns,避免动态宽度干扰
data: tableData,
columns: [
{ title: 'Name', field: 'name', width: 175, resizable: false },
{ title: 'Age', field: 'age', width: 100, resizable: false },
{ title: 'Gender', field: 'gender', width: 100, resizable: false },
{ title: 'Favourite Color', field: 'col', width: 150 },
{ title: 'Date Of Birth', field: 'dob' }
],
rowFormatter: (row: RowComponent) => {
const data = row.getData();
// 条件触发:例如当 color 为 'blue' 时合并前三列
if (data.col === 'blue') {
const rowEl = row.getElement();
const cells = Array.from(rowEl.children) as HTMLElement[];
// 提取需合并的前3个单元格(索引0,1,2)
const [c1, c2, c3, ...rest] = cells;
if (!c1 || !c2 || !c3) return;
// 计算合并后总宽度(单位:px)
const totalWidth = [
parseInt(c1.style.width) || c1.offsetWidth,
parseInt(c2.style.width) || c2.offsetWidth,
parseInt(c3.style.width) || c3.offsetWidth
].reduce((a, b) => a + b, 0);
// 创建合并容器
const mergedCell = document.createElement('div');
mergedCell.className = 'tabulator-cell';
mergedCell.style.width = `${totalWidth}px`;
mergedCell.style.fontWeight = '600';
mergedCell.style.backgroundColor = '#f8f9fa';
mergedCell.style.borderRight = '1px solid #dee2e6';
mergedCell.innerHTML = `? 汇总信息:${data.name}(${data.age}岁,${data.gender})`;
// 替换 DOM:用 mergedCell 替代前三个单元格,后接剩余列
rowEl.replaceChildren(mergedCell, ...rest);
}
}
});
? 动态添加合并行(进阶用法)
若需在运行时插入新合并行(如点击按钮添加),可结合 table.addRow() 与 rowFormatter 的条件逻辑:
// 添加一条“虚拟”合并行数据(不参与排序/过滤,仅用于渲染)
table.addRow({
id: 'merge-row-1',
_isMergedRow: true,
content: '自定义跨列说明文字'
}, true); // true 表示追加至末尾
// 在 rowFormatter 中扩展判断:
rowFormatter: (row) => {
const data = row.getData();
if (data._isMergedRow) {
const rowEl = row.getElement();
const cells = Array.from(rowEl.children);
const merged = document.createElement('div');
merged.className = 'tabulator-cell';
merged.style.gridColumn = '1 / -1'; // CSS Grid 方案(Tabulator v6+ 更推荐)
merged.textContent = data.content;
rowEl.replaceChildren(merged);
}
}
? 总结:
rowFormatter是实现 Tabulator 跨列合并最直接、低侵入的方案。它绕过框架限制,赋予开发者完全的 DOM 控制权。尽管需手动管理宽度与样式,但在 TypeScript 工程中可封装为可复用的mergeRow()工具函数,显著提升维护性与一致性。










