
本文介绍如何使用原生 javascript 实现表格的动态增行与删行,并确保删除后剩余行的序号(如第一列输入框中的数字)保持连续递增,避免手动重排逻辑。
本文介绍如何使用原生 javascript 实现表格的动态增行与删行,并确保删除后剩余行的序号(如第一列输入框中的数字)保持连续递增,避免手动重排逻辑。
在构建可编辑的动态表格时,常见的需求是:点击“add”按钮新增一行,且首列序号自动递增;点击对应行的“delete”按钮则移除该行,并自动更新其余行的序号以维持连续性。原始方案虽实现了删除,但未重置序号——这会导致序号断层(如删除第2行后,剩下1、3、4),影响数据一致性与用户体验。
以下是完整、健壮的实现方案:
✅ 核心改进点
- addRow():仍基于最后一行值递增生成新序号;
- deleteRow():不仅删除当前行,还调用 reindexRows() 重新填充所有剩余行的序号;
- 所有操作均通过 document.getElementById('dataTable') 安全获取表格,避免依赖 DOM 顺序异常。
✅ 完整代码示例
<table border="1">
<thead>
<tr>
<th>#</th>
<th>item1</th>
<th>item2</th>
<th>操作</th>
</tr>
</thead>
<tbody id="dataTable" class="table">
<tr>
<td><input type="text" value="1" name="chk[]" readonly></td>
<td><input type="text" value="" name="chk[]"></td>
<td><input type="text" value="" name="chk[]"></td>
<td>
<button type="button" onclick="addRow('dataTable')">+ 添加</button>
<button type="button" onclick="deleteRow(this)">− 删除</button>
</td>
</tr>
</tbody>
</table>
<script>
function addRow(tableID) {
const table = document.getElementById(tableID);
const rowCount = table.rows.length;
const lastRow = table.rows[rowCount - 1];
const lastValue = parseInt(lastRow.cells[0].querySelector('input').value) || 0;
const row = table.insertRow(rowCount);
const templateRow = table.rows[0]; // 复制首行结构(含 input 和按钮)
const colCount = templateRow.cells.length;
for (let i = 0; i < colCount; i++) {
const newCell = row.insertCell(i);
newCell.innerHTML = templateRow.cells[i].innerHTML;
}
// 设置新行序号
row.cells[0].querySelector('input').value = lastValue + 1;
}
function deleteRow(button) {
const row = button.closest('tr');
row.parentNode.removeChild(row);
reindexRows('dataTable'); // 删除后立即重索引
}
function reindexRows(tableID) {
const table = document.getElementById(tableID);
const rows = Array.from(table.querySelectorAll('tbody tr'));
rows.forEach((row, index) => {
const input = row.cells[0].querySelector('input');
if (input) {
input.value = index + 1; // 从 1 开始连续编号
}
});
}
</script>⚠️ 注意事项
- 避免 innerHTML 复制事件丢失问题:本例中按钮绑定的是内联 onclick,若改用 addEventListener,需在 addRow() 中显式绑定新按钮事件。
- readonly 保护序号列:首列 <input> 加 readonly 属性防止用户误改,确保序号仅由逻辑控制。
- 兼容性优化:使用 closest('tr') 替代 parentNode.parentNode,语义更清晰、层级变动时更鲁棒。
- 空表处理:若支持初始无行,addRow() 需增加 if (rowCount === 0) 分支,设初始值为 1。
✅ 总结
该方案不仅解决了“点击删除按钮即移除当前行”的基础需求,更关键的是通过 reindexRows() 在每次删除后统一重置全部有效行的序号,保障了数据序列的完整性与可预测性。配合语义化 HTML 结构与现代 DOM API(如 closest()、querySelector),代码更易维护、扩展性强,适用于表单采集、订单明细、配置项管理等典型业务场景。

















