首先是vue代码
<template><div id="body-container"style="position: absolute"><div class="box-container"><div class="lsb-table-box" ><div class="table-container" id="lsb-table"></div></div></div></div></template>
然后是js方法
/*** 渲染表格*/
function tableRenderCs() {const data=[{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"},{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"},{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"}]let html = '<table class="table-wj JZ-A" border="1" cellspacing="0">' +'<thead>' +'<tr>' +'<th rowspan="2" colspan="3">第一列</th>' +'<th rowspan="2" colspan="1" style="width: 50px;">第二列</th>' +'<th rowspan="2" colspan="1" style="width: 100px;">第三列</th>' +'<th rowspan="2" colspan="1" style="width: 50px;">第四列</th>' +'<th rowspan="2" colspan="1" style="width: 80px;">第五列</th>' +'<th rowspan="1" colspan="3">第六列</th>' +'</tr>' +'<tr>' +'<th colspan="1" style="width: 50px;">第六列的第一列</th>' +'<th colspan="1" style="width: 90px;">第六列的第二列</th>' +'</tr>' +'</thead>' +'<tbody>';for (let i = 0; i < data.length; i++) {const item = data[i];html +=`<tr>` +`<td>${item.one}</td>` +`<td>${item.two}</td>` +`<td>${item.three}</td>` +`<td>${item.four}</td>` +`<td>${item.five}</td>` +`<td>${item.six}</td>` +`<td>${item.seven}</td>` +`<td>${item.eight}</td>` +`<td>${item.nine}</td>` +`</tr>`;}html += '</tbody></table>';let _$ = $(".lsb-table-box .table-container");_$.append(html);//存储列名对应的字段值,方便后面计算let rowName = {'0': 'one','1': 'two','2': 'three','3': 'four','4': 'five','5': 'six','6': 'seven','7': 'eight','8': 'nine',}editInput(_$, data, "two", rowName);mergeColumns(); //调用动态合并行的方法
}/*** 执行合并逻辑*/
function mergeColumns() {let $table = $('table.table-wj');let $rows = $table.find('tbody tr');const numCols = $rows.eq(0).find('td').length;//考虑全部列//const numCols = Math.min(3, $rows.eq(0).find('td').length); // 仅考虑前三列// 遍历每列for (let col = 1; col <= numCols; col++) {let $currentColumn = $table.find(`td:nth-child(${col})`);let prevContent = null;let rowspan = 1;for (let i = 0; i < $currentColumn.length; i++) {let $currentCell = $($currentColumn[i]);let currentContent = $currentCell.text();if (currentContent === prevContent) {rowspan++;$currentCell.addClass('hidden');} else {if (rowspan > 1) {$currentColumn.eq(i - rowspan).attr('rowspan', rowspan);}prevContent = currentContent;rowspan = 1;}}if (rowspan > 1) {$currentColumn.eq($currentColumn.length - rowspan).attr('rowspan', rowspan);}}// 清除被隐藏的单元格$table.find('.hidden').remove();
}
const numCols这里给出了两种合并表格的逻辑,第一个是只会对前三列执行合并逻辑,而第二个会对所有列执行合并逻辑。下面是两种逻辑的合并效果图。
接下来是使单元格可以被编辑,并且获取到编辑后的值,以及单元格位置
在上面的方法中调用即可editInput(_$, data, "two", rowName); //这里的four是上面 `<td>${item.four}</td>` 对应的字段名,也就是列名mergeColumns(); //这里一定要注意先调用editInput方法再调用mergeColumns,不然获取编辑单元格的列索引会有问题/*** 设置单元格可编辑* @param _$ 表对象* @param data 表数据* @param fieldName 编辑后要获取的值对应的列名* @param rowName 列的索引与数据库字段相对应的集合*/
function editInput(_$, data, fieldName, rowName) {// 获取所有表格单元格let cells = _$.find('td');// 为每个单元格添加点击事件cells.each(function (index) {let column = $(this).index();let row = $(this).closest('tr').index();let columnName = Object.keys(data[0])[column]; // 获取对应列的字段名$(this).data('columnName', columnName); // 存储列名为数据属性$(this).on('mousedown', function (event) {// 如果是鼠标右键点击,不进行操作if (event.which === 3) return;let $input = $(this).find('input'); // 检查单元格内是否已有输入框if ($input.length === 0) { // 如果没有输入框,则进行以下操作let currentValue = $(this).text();// 创建一个输入框元素,并将当前单元格内容设置为其值$input = $('<input type="text">');$input.val(currentValue);// 设置输入框的样式$input.css({'background-color': 'transparent', // 设置背景色为透明'color': 'white', // 设置文字颜色为白色'border': 'none', // 移除边框'outline': 'none', // 移除外边框});// 清空单元格并将输入框添加到单元格中$(this).empty().append($input);// 焦点定位到输入框$input.focus();// 阻止默认行为event.preventDefault();// 处理输入框失去焦点事件$input.on('blur', function () {let newValue = $input.val();let valueName = rowName[column]; // 获取列索引对应的字段名称let columnValue = data[row][fieldName]; // 获取对应字段的值console.log('编辑后的内容:', newValue);console.log('所在单元格位置:', '行:', row, '列:', column);console.log('所在列字段名:', valueName);console.log(fieldName + '列的值:', columnValue);console.log(`更改了${fieldName}为${columnValue}的字段${valueName}的值为${newValue}`)$(this).parent('td').text(newValue);});}});});
}
实现效果如下,同时还获取了当前单元格所在行里面指定的某一列的数据内容(比如可以获取当前行的id,以此来给后端修改数据库中的数据),注意行是从表头下面开始的,行和列的下标都是从0开始