必须在done回调中手动操作DOM实现单元格合并,因Layui表格异步渲染且cols不支持rowspan;需三步闭环(清旧→比对→设值),注意跨页、空值及固定列分离问题。

必须在 done 回调里手动操作 DOM,其他任何位置写合并逻辑都会失效——表格是异步渲染的,table.render() 调用后 DOM 还没生成,$('#demo').find('td') 必然为空。
为什么不能在 cols 配置里加 rowspan
Layui 的 cols 数组只接受静态结构,写 {field: 'deptName', rowspan: 2} 完全被忽略。它不是 HTML 表格的配置层,而是数据映射层;rowspan 是 DOM 层级属性,必须等真实 <td> 挂载后才能设置。
<ul>
<li>所有“自动合并”尝试(比如在 <code>templet 里返回空字符串、或靠 CSS 视觉模拟)在分页、排序、重载后立即崩坏
height 或 scroll 时更危险:虚拟滚动会复用 <tr> 元素,导致 rowspan 挂错行,且无法预测
<li>固定列(<code>fixed: 'left')单独渲染在另一个 <table> 中,和主表索引不互通,硬算列序必出错
<h3>怎么安全获取目标列的真实索引</h3>
<p>你配置的 <code>{field: 'category'} 在 DOM 中不一定是第 0 列——前面可能有复选框、序号、操作列。不能写死 colIndex = 0。
- 打开浏览器开发者工具,inspect 目标
<td>,看它是 <code><tr> 的第几个子节点(从 0 开始计数) <li>或用 <code>$('th[data-field="category"]').index()获取表头列序,通常与数据行一致 - 若该列设了
fixed: 'left',必须单独查$('.layui-table-fixed-l table tbody tr'),不能混进主表遍历
合并逻辑必须三步闭环:清旧 → 比对 → 设值
漏掉任一环,翻页后就会叠加错乱。示例合并第 2 列(字段为 'deptName'):
done: function(res, curr, count) {
const $tbody = $('#demo + .layui-table-box .layui-table-body tbody');
const $trs = $tbody.find('tr');
// ① 清旧:每次执行前先清除历史 rowspan 和 display
$trs.find('td').each(function() {
this.removeAttribute('rowspan');
this.style.display = '';
});
// ② 比对:按列独立维护状态(多列合并不能共用变量)
let currentVal = null;
let startRow = 0;
let rowspan = 1;
for (let i = 0; i < $trs.length; i++) {
const $td = $($trs[i]).find('td').eq(2); // 注意:这里是真实列索引,非 field 顺序
const text = $td[0]?.textContent?.trim() || '';
if (text === currentVal && i > 0) {
rowspan++;
$td.hide(); // 隐藏后续重复单元格
} else {
// ③ 设值:给首行 td 设置 rowspan,并重置
if (rowspan > 1) {
$($trs[startRow]).find('td').eq(2).attr('rowspan', rowspan);
}
currentVal = text;
startRow = i;
rowspan = 1;
}
}
// 处理最后一组
if (rowspan > 1) {
$($trs[startRow]).find('td').eq(2).attr('rowspan', rowspan);
}
}
- 比对必须用
textContent.trim(),不用innerHTML(图标、空格、换行会导致误判) - 遇到
null/undefined要显式判断:!val && !prevVal才算相等,否则null === undefined为 true 但语义错误 - 必须跳过已设
rowspan > 1的行,否则重复计算导致跨行错位
最易被忽略的是跨页边界、空字段、固定列分离这三种情况——测试数据往往不覆盖,上线后才在特定组合下突然失效。


















