返回
进阶掌握:解密通用表格合并单元格的极佳极简方案
前端
2023-10-03 07:44:50
在日复一日的程序员工作中,表格的身影随处可见,合并单元格似乎更是一个避不开的难题。从前都是临时抱佛脚,遇到一个表格就针对性地解决一次,这确实很繁琐。于是,作为一个颇具匠心的开发者,我决定一劳永逸,亲手打造一款极佳极简的通用表格合并单元格方案。
过去几年我经手的表格形形色色,有的表格仅仅几行几列,有的却如同数据库查询结果一般动辄几十上百行。这么多年来,表格始终伴随左右,而作为程序员,自然离不开合并单元格。
合并单元格,在程序员的眼中,那绝对是一门艺术。网上也存在不少的解决方案,有涉及JavaScript
的,也有涉及jQuery
的,更有纯CSS
的。然而,它们的共同点是,对于普通的开发者来说,学习和使用成本偏高,因此最终没有被广泛推广开来。
完美主义者的全新方案
既然现有方案都不尽人意,那就自己动手吧。我决定亲手打造一个通用、极简的表格合并单元格方案,它的特点是:
- 简单易用
- 性能卓越
- 跨浏览器
- 跨平台
该方案仅依赖JavaScript
和CSS
,无需任何第三方库。开发者只需要引入这两个文件,即可在任何网页中使用该方案。
精妙的实现思路
那么,这个方案的实现思路是什么呢?
- 首先,我们对表格进行网格布局。
- 其次,我们利用
JavaScript
来监听表格的事件,如鼠标点击、鼠标拖拽等。 - 当用户触发这些事件时,我们就通过
JavaScript
来控制单元格的合并和拆分。 - 最后,我们利用
CSS
来控制合并单元格的样式。
炉火纯青的编码实践
下面,我们就来看看如何实现这个方案吧。
- 首先,我们在
HTML
中创建一个表格,并为其添加网格布局。
<table class="grid">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
</tr>
<tr>
<td>李四</td>
<td>25</td>
<td>女</td>
</tr>
<tr>
<td>王五</td>
<td>30</td>
<td>男</td>
</tr>
</tbody>
</table>
- 其次,我们在
JavaScript
中监听表格的事件。
const grid = document.querySelector('.grid');
grid.addEventListener('click', function(e) {
const target = e.target;
if (target.tagName === 'TH') {
// 单击表头时,选中该列的所有单元格
const column = target.cellIndex;
const cells = grid.querySelectorAll(`td:nth-child(${column + 1})`);
cells.forEach(cell => {
cell.classList.add('selected');
});
} else if (target.tagName === 'TD') {
// 单击单元格时,选中该单元格
target.classList.add('selected');
}
});
grid.addEventListener('mousedown', function(e) {
const target = e.target;
if (target.tagName === 'TH' || target.tagName === 'TD') {
// 按下鼠标时,记录起始单元格
const startCell = target;
// 监听鼠标移动事件
document.addEventListener('mousemove', function(e) {
// 计算鼠标移动的距离
const deltaX = e.clientX - startCell.getBoundingClientRect().left;
const deltaY = e.clientY - startCell.getBoundingClientRect().top;
// 根据鼠标移动的距离,调整选中的单元格
const cells = grid.querySelectorAll('.selected');
cells.forEach(cell => {
const cellRect = cell.getBoundingClientRect();
const left = cellRect.left + deltaX;
const top = cellRect.top + deltaY;
const width = cellRect.width;
const height = cellRect.height;
cell.style.left = `${left}px`;
cell.style.top = `${top}px`;
cell.style.width = `${width}px`;
cell.style.height = `${height}px`;
});
});
// 监听鼠标松开事件
document.addEventListener('mouseup', function() {
// 松开鼠标时,停止监听鼠标移动事件
document.removeEventListener('mousemove');
// 合并选中的单元格
const cells = grid.querySelectorAll('.selected');
const startCellRect = startCell.getBoundingClientRect();
const endCellRect = cells[cells.length - 1].getBoundingClientRect();
const left = Math.min(startCellRect.left, endCellRect.left);
const top = Math.min(startCellRect.top, endCellRect.top);
const width = Math.max(startCellRect.right, endCellRect.right) - left;
const height = Math.max(startCellRect.bottom, endCellRect.bottom) - top;
const mergedCell = document.createElement('td');
mergedCell.style.left = `${left}px`;
mergedCell.style.top = `${top}px`;
mergedCell.style.width = `${width}px`;
mergedCell.style.height = `${height}px`;
mergedCell.colSpan = cells.length;
startCell.parentNode.replaceChild(mergedCell, startCell);
// 移除选中的样式
cells.forEach(cell => {
cell.classList.remove('selected');
});
});
}
});
- 最后,我们在
CSS
中控制合并单元格的样式。
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
}
.grid td {
border: 1px solid #ccc;
padding: 5px;
}
.grid .selected {
background-color: #999;
}
.grid .merged-cell {
background-color: #666;
color: #fff;
font-weight: bold;
text-align: center;
}
结语
现在,您已经掌握了通用表格合并单元格的极佳极简方案。您只需引入JavaScript
和CSS
文件,即可在任何网页中使用该方案。相信我,它一定会让您的工作更加轻松。