如何修复DataTable的stateSave功能使其正常工作?
DataTable stateSave 失效问题解决
问题现象
启用DataTable的stateSave功能后,用户选择项目返回页面时,表格总是重置回第一页,无法停留在之前的页码。尝试使用activeTable.draw(false)和inactiveTable.draw(false)无效,注释.clear()方法也没用,不调用.draw()则无法显示行数据。
问题根源
页面加载时先初始化DataTable(已开启stateSave),随后立刻发起AJAX请求获取数据,接着执行.clear()清空表格、.row.add()添加新行、.draw()渲染的流程。这个过程会完全替换表格数据集,DataTable会判定为新数据,从而忽略之前保存的分页状态,强制回到第一页。
解决方案
方案一:先获取数据,再初始化DataTable
将数据获取放在表格初始化之前,确保初始化时直接加载完整数据,让stateSave能正确应用保存的状态。
修改后的代码示例:
window.onload = Init; var activeCnt = 0, inactiveCnt = 0; var activeTable, inactiveTable; function Init() { // 先获取数据,再初始化表格 GetProjectsList(); } function GetProjectsList() { $.ajax({ url: "/Projects/GetProjects", type: 'GET', success: function (dta) { view = dta; // 数据获取完成后初始化表格并填充数据 InitTables(); PopulateProjectTable(); } }); } function InitTables() { activeTable = $('#activeTable').DataTable({ order: [[0, 'asc']], columnDefs: [ { targets: -1, className: 'text-center' } ], stateSave: true, // 初始化时不自动绘制,等数据添加完成后再手动绘制 deferRender: true }); inactiveTable = $('#inactiveTable').DataTable({ order: [[0, 'asc']], columnDefs: [ { targets: -1, className: 'text-center' } ], stateSave: true, deferRender: true }); } function PopulateProjectTable() { activeCnt = 0; inactiveCnt = 0; for (var i = 0; i < view.projects.length; i++) { var prj = view.projects[i]; var hrTtl = (prj.Sums != null) ? prj.Sums.PrjTotalHours : 0; if (prj.PrjStatusID == 1) { activeTable.row.add([ prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.", `<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit add-pointer text-primary" onclick="EditProject(${prj.PrjID})" data-bs-toggle="modal" data-bs-target="#modal-prj-details"></i>` ]); activeCnt++; } else { inactiveTable.row.add([ prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.", prj.PrjStatusName, `<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit no-click text-secondary"></i>` ]); inactiveCnt++; } } activeTable.draw(); inactiveTable.draw(); document.getElementById("actCnt").innerHTML = activeCnt; document.getElementById("inactCnt").innerHTML = inactiveCnt; }
方案二:保留原初始化流程,手动恢复分页状态
如果必须先初始化表格再加载数据,可以先读取stateSave保存的页码,在数据填充完成后手动跳转到该页码。
修改PopulateProjectTable函数:
function PopulateProjectTable() { activeCnt = 0; inactiveCnt = 0; // 先获取保存的分页状态 var activePage = activeTable.state.loaded()?.start / activeTable.page.info().length || 0; var inactivePage = inactiveTable.state.loaded()?.start / inactiveTable.page.info().length || 0; activeTable.clear(); inactiveTable.clear(); // 循环添加行数据(原逻辑不变) for (var i = 0; i < view.projects.length; i++) { var prj = view.projects[i]; var hrTtl = (prj.Sums != null) ? prj.Sums.PrjTotalHours : 0; if (prj.PrjStatusID == 1) { activeTable.row.add([prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.", `<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit add-pointer text-primary" onclick="EditProject(${prj.PrjID})" data-bs-toggle="modal" data-bs-target="#modal-prj-details"></i>`]); activeCnt++; } else { inactiveTable.row.add([prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.", prj.PrjStatusName, `<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit no-click text-secondary"></i>`]); inactiveCnt++; } } // 绘制表格后跳转到保存的页码 activeTable.draw(false).page(activePage).draw(false); inactiveTable.draw(false).page(inactivePage).draw(false); document.getElementById("actCnt").innerHTML = activeCnt; document.getElementById("inactCnt").innerHTML = inactiveCnt; }
关键说明
- 方案一从根源避免了状态覆盖问题,是更推荐的实现方式。
- 方案二中,
state.loaded()可以获取到之前保存的状态,start是当前页的起始索引,除以每页条数得到页码。
内容的提问来源于stack exchange,提问作者DaBeau96
相关产品推荐
相关产品推荐

