
本文介绍一种递归式 javascript 行合并方案,可精准实现多列联动合并:仅当左侧所有列值均相同时,当前列才允许合并,完美解决“同值但需分组”的复杂场景。
本文介绍一种递归式 javascript 行合并方案,可精准实现多列联动合并:仅当左侧所有列值均相同时,当前列才允许合并,完美解决“同值但需分组”的复杂场景。
在动态渲染的 HTML 表格中,简单地对某列执行 rowSpan 合并(如逐列独立处理)极易导致视觉错位或语义断裂——例如当第一列值变化时,第二列即使内容相同也不应跨组合并。本方案采用层级依赖合并策略:从左到右、自上而下,严格遵循「前序列已合并为同一逻辑组」的前提,才对当前列进行合并判断。
核心思想是递归分治:对第 startCol 列,在指定行范围 [startRow, endRow) 内识别连续相同值的行段;对每个满足合并条件的行段 [cellStart, r),先递归处理其右侧列(startCol + 1 至 endCol)在该行段内的子范围,再统一设置 rowSpan 并移除冗余单元格。
以下是完整、健壮的实现代码:
function mergeCells(table, startCol, endCol, startRow, endRow) {
let cell = null;
let cellStart = 0;
// 辅助函数:触发当前列在 [cellStart, r) 区间内的合并
function mergeCell(r) {
if (cell && r > cellStart + 1) {
// 若未达最右列,先递归处理右侧列(限定在同一行段内)
if (startCol < endCol) {
mergeCells(table, startCol + 1, endCol, cellStart, r);
}
// 设置 rowspan 并移除后续重复单元格
cell.rowSpan = r - cellStart;
for (let s = cellStart + 1; s < r; s++) {
table.rows[s].cells[startCol].remove();
}
}
}
// 遍历指定行范围,识别连续相同值区间
for (let r = startRow; r < endRow; r++) {
const curCell = table.rows[r].cells[startCol];
if (!cell || curCell.textContent !== cell.textContent) {
mergeCell(r); // 提交上一段
cell = curCell;
cellStart = r;
}
}
mergeCell(endRow); // 提交最后一段
}
// 使用示例:对 #myTable 的第 0~2 列(共3列),从第1行(索引1,跳过表头)开始合并
const table = document.getElementById('myTable');
if (table && table.rows.length > 1) {
mergeCells(table, 0, 2, 1, table.rows.length);
}✅ 关键特性说明:
立即学习“Java免费学习笔记(深入)”;
-
层级感知:
BBB1在AAA1组与AAA2组中分别独立合并,互不影响; -
安全边界:自动跳过
<thead>(通过 <code>startRow = 1),避免误操作表头; -
空值鲁棒:使用
textContent比较,兼容空白、换行等格式差异; - DOM 稳定:先计算再批量移除,避免遍历时 DOM 结构变动引发索引错乱。
- 表格必须为标准结构(
<tr> 直接子元素为 <code><td> 或 <code><th>); <li>合并列需保证每行单元格数量一致,否则 <code>cells[startCol]可能为undefined; - 建议在表格完全渲染后(如
DOMContentLoaded或window.onload)调用; - 如需支持动态更新,应在数据变更后重新执行
mergeCells(注意重置rowSpan和恢复被删节点需额外逻辑)。
⚠️ 注意事项:
此方案将“条件化行合并”转化为可复用、可扩展的递归过程,适用于报表汇总、分组统计、树形数据展开等多种业务场景,兼顾准确性与工程实用性。


















