jQuery DataTable重复数据问题:新增记录时保留旧数据如何解决?
问题分析
你遇到的重复行问题,核心原因是重复绑定了点击事件。每次调用drawDataTable函数时,你都会给隐藏按钮#addRows绑定一次click事件,但之前绑定的事件并没有被移除。这样多次调用后,执行$('#addRows').click()时,会触发所有历史绑定的事件,导致旧数据被重复添加,和新数据叠加出现重复行。
另外,虽然你调用了table.destroy()销毁旧实例,但DOM上的事件绑定不会随着DataTable实例销毁而自动移除,这也是问题的关键所在。
解决方案
这里提供几种可行的修复方式,按推荐程度排序:
方案1:直接用DataTable的data选项初始化数据(最简洁高效)
不需要借助隐藏按钮触发添加行,直接在初始化DataTable时传入整组数据,这也是DataTable官方推荐的用法:
function drawDataTable(pData) { console.log("Call of drawDataTable!!!"); // 显示表格卡片 document.getElementById("dataTableCard").style.display = "block"; // 销毁旧的DataTable实例 const table = $('#dataTable').DataTable(); table.destroy(); // 把pData转换成DataTable需要的二维数组格式 const p1 = pData['p1']; const p2 = pData['p2']; const p3 = pData['p3']; const p4 = pData['p4']; const p5 = pData['p5']; const p6 = pData['p6']; const tableData = []; for (const idxT in p1) { tableData.push([ p1[idxT], p2[idxT], p3[idxT], p4[idxT], p5[idxT], p6[idxT] ]); } // 初始化新表格,直接传入数据 $('#dataTable').DataTable({ "scrollY": "400px", "paging": false, "data": tableData // 这里直接传入整理好的数据 }); }
方案2:绑定事件前先解绑旧事件
如果你坚持要保留隐藏按钮的逻辑,需要在每次绑定新事件前,移除之前绑定的所有click事件:
function drawDataTable(pData) { console.log("Call of drawDataTable!!!"); document.getElementById("dataTableCard").style.display = "block"; const table = $('#dataTable').DataTable(); table.destroy(); const newTable = $('#dataTable').DataTable({ "scrollY": "400px", "paging": false }); const p1 = pData['p1']; const p2 = pData['p2']; const p3 = pData['p3']; const p4 = pData['p4']; const p5 = pData['p5']; const p6 = pData['p6']; // 关键:先解绑所有click事件,再绑定新的 $('#addRows').off('click').on('click', function() { // 清空现有行(可选,确保万无一失) newTable.clear(); for (const idxT in p1) { newTable.row.add([ p1[idxT], p2[idxT], p3[idxT], p4[idxT], p5[idxT], p6[idxT] ]).draw(false); } }); $('#addRows').click(); }
这里额外加上了newTable.clear(),可以确保添加新数据前表格是空的,双重保障避免重复。
方案3:使用事件委托(适合频繁创建销毁实例的场景)
把事件绑定到父元素上,利用事件委托机制,避免重复绑定:
// 只需要在页面初始化时绑定一次,不用放在drawDataTable里 $('#dataTableCard').on('click', '#addRows', function() { const table = $('#dataTable').DataTable(); table.clear(); // 从按钮的data属性中获取当前要加载的数据 const pData = $(this).data('tableData'); const p1 = pData['p1']; const p2 = pData['p2']; const p3 = pData['p3']; const p4 = pData['p4']; const p5 = pData['p5']; const p6 = pData['p6']; for (const idxT in p1) { table.row.add([ p1[idxT], p2[idxT], p3[idxT], p4[idxT], p5[idxT], p6[idxT] ]).draw(false); } }); function drawDataTable(pData) { console.log("Call of drawDataTable!!!"); document.getElementById("dataTableCard").style.display = "block"; const table = $('#dataTable').DataTable(); table.destroy(); $('#dataTable').DataTable({ "scrollY": "400px", "paging": false }); // 把pData存在按钮的data属性里,供事件委托的回调使用 $('#addRows').data('tableData', pData); $('#addRows').click(); }
这种方式适合表格频繁创建销毁的场景,避免重复绑定事件的问题。
总结
最推荐方案1,既符合DataTable的设计逻辑,又能彻底避免事件绑定带来的问题,代码也更简洁易维护。
内容的提问来源于stack exchange,提问作者user9324524
相关产品推荐
相关产品推荐

