You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:47:36