原生javascript模拟excel合并单元格需手动维护选区状态:mousedown记录起点,mousemove实时计算行列索引并高亮矩形区域,mouseup后校验结构合法性(无跨区域/已合并单元格),再移除被覆盖单元格、设置主单元格rowspan/colspan。

如何用原生 JavaScript 模拟 Excel 的合并单元格拖选交互
不能直接复用 Excel 的 UI 逻辑,浏览器中 <table> 的 <code>rowspan/colspan 是静态声明式属性,不支持运行时“画框选区→一键合并”这种动态行为。必须自己维护选区状态、计算合并范围、重写 DOM 结构,并拦截鼠标事件模拟拖拽反馈。
监听 mousedown + mousemove 实现视觉选区框
关键不是画一个 div 覆盖层,而是实时计算鼠标经过的 <td> 或 <code><th> 单元格坐标(行索引、列索引),再根据起始点和当前点确定矩形区域。浏览器原生没有“单元格坐标映射”,得靠 <code>cellIndex 和 rowIndex 属性手动提取:
- 在
<table> 上绑定 <code>mousedown,记录起点startRow/startCol - 立刻绑定
document.mousemove,用event.target.closest('td, th')获取当前单元格,再读取其rowIndex和cellIndex - 每次移动都清除旧的临时高亮(比如加
temp-selectedclass),再对矩形区域内所有单元格批量添加该 class - 必须在
mouseup后解绑mousemove,否则会持续触发 - 确定主单元格(通常是左上角那个)
- 按行优先顺序遍历选区,跳过主单元格,对其他所有单元格调用
.remove() - 最后设置主单元格的
rowSpan和colSpan属性(注意:用setAttribute('rowspan', ...),不是rowSpan = ...,后者不触发重排) - 如果要保留原始内容,需提前把所有被删单元格的
textContent合并到主单元格(例如用换行符分隔)
合并前必须校验:哪些单元格能真正合并
Excel 允许合并的前提是内容一致且结构允许;HTML 表格里更严格——合并后必须满足:rowspan × colspan 覆盖的格子不能已有其他 rowspan/colspan 干扰,且不能跨表头/表体边界(<thead> 和 <code><tbody> 分开处理)。常见错误现象:
<ul><li>点击合并后部分单元格消失 → 某个 <code><td rowspan="2"> 挡住了下方本该被合并的格子
<li>合并结果错位一格 → 起始单元格在 <code><thead>,但代码没判断,把 <code><tbody> 的第一行也卷进去了
<li>
<code>colspan 合并后右侧单元格错乱 → 没先移除被覆盖单元格的 colspan 属性,导致渲染重叠
实操建议:遍历选区内每个单元格,检查其 rowSpan 和 colSpan 是否为 1;若任一不为 1,则整个合并操作应拒绝并提示“存在已合并单元格”。
执行合并时,DOM 操作顺序不能错
合并不是简单设 rowSpan/colSpan 就完事。必须先删掉被覆盖的单元格,再设置主单元格的跨度,否则浏览器渲染会出错。典型步骤:
容易被忽略的是:合并后,后续所有基于 cellIndex 的逻辑(比如编辑、复制)都会失效——因为表格结构已变,必须重建索引缓存或改用 querySelectorAll('td, th') 重新定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











