AJAX刷新后Client-Side DataTable分页失效(单页显示)修复问询
解决DataTables AJAX刷新后分页失效的问题
这个问题我之前也踩过坑——核心原因是你现在的操作同时混合了手动修改DOM和DataTables自带的AJAX刷新,导致DataTables的内部数据状态和实际DOM不一致,分页、排序这些依赖内部状态的功能自然就失效了。
为什么你的代码会出问题?
你在AJAX提交成功后,先通过$.get替换了#table-body的HTML内容,然后又调用了$("#earnings_amendment_account").DataTable().ajax.reload()。这两步操作完全冲突:
- 手动替换DOM会让DataTables丢失对表格数据的控制权,它还停留在初始化时的旧数据状态,根本不知道DOM已经更新了。
ajax.reload()是给配置了ajax数据源的DataTables用的,而你的初始化代码并没有设置这个选项,所以这行代码其实起不到正确的刷新作用,反而会干扰DataTables的状态。
修复方案(两种可选)
方案一:快速适配现有代码,刷新后重新初始化DataTables
这种方式不需要修改后端代码,只需要调整前端的AJAX回调逻辑,让DataTables重新识别新的DOM内容:
- 先把DataTables的初始化和事件绑定封装成一个可复用的函数,避免重复写代码:
// 封装DataTables初始化逻辑 function initEarningsTable() { // 先销毁已存在的DataTables实例(防止重复初始化报错) if ($.fn.DataTable.isDataTable('#earnings_amendment_account')) { $('#earnings_amendment_account').DataTable().destroy(); } // 重新初始化DataTable window.earnings_amendment_account_table = $('#earnings_amendment_account').DataTable({}); // 重新绑定详情展开/收起的事件(因为DOM更新后,旧的事件绑定会失效) $('#earnings_amendment_account').off('click', 'td.details-control').on('click', 'td.details-control', function () { var tr = $(this).closest('tr'); var row = earnings_amendment_account_table.row(tr); if (row.child.isShown()) { // 关闭详情 row.child.hide(); tr.removeClass('shown'); } else { // 打开详情 row.child(format({ 'Posted By': tr.data('key-1'), 'Date Posted': tr.data('key-2'), 'Approved By': tr.data('key-3'), 'Date Approved': tr.data('key-4') })).show(); tr.addClass('shown'); } }); } // 页面加载完成后初始化表格 $(document).ready(function() { initEarningsTable(); });
- 修改你的
SubmitFormData函数里的AJAX回调,去掉无效的ajax.reload(),换成调用封装好的初始化函数:
function SubmitFormData() { var add = $("#add").val(); var add_accountcode = $("#add_accountcode").val(); var accounttitle = $("#accounttitle").val(); var accounttype = $("#accounttype").val(); var postedby = $("#postedby").val(); var dateposted = $("#dateposted").val(); $.post("earnings_amendment_account_add.php", { add: add, add_accountcode: add_accountcode, accounttitle: accounttitle, accounttype: accounttype, postedby: postedby, dateposted: dateposted }, function(data) { $('#results').html(data); $('#myForm')[0].reset(); // 更新表格内容后重新初始化DataTables,让它识别新数据 $.get("tableBody.php", function(tableHtml) { $("#table-body").html(tableHtml); initEarningsTable(); // 关键步骤:重新初始化表格 }); }); }
方案二:改用DataTables自带的AJAX数据源(更优雅规范)
如果想彻底遵循DataTables的设计逻辑,避免手动操作DOM的麻烦,可以修改后端返回JSON数据,让DataTables自己处理数据渲染和状态维护:
- 修改
tableBody.php,让它返回JSON格式的账户数据(而不是HTML行):
<?php include 'backend/conn.php'; $params = array(); $sql = "SELECT accountcode,accounttype,accounttitle,postedby,dateposted,approvedby,dateapproved FROM earningsamendmentaccount"; $query = sqlsrv_query($conn, $sql, $params, array("Scrollable" => SQLSRV_CURSOR_KEYSET)); if ($query === false ) { echo json_encode(array('error' => "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true))); exit; } $data = array(); while($row = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC)){ // 将SQL Server的日期对象转为字符串(避免JSON序列化问题) $dateposted = $row['dateposted'] ? $row['dateposted']->format('Y-m-d H:i:s') : ''; $dateapproved = $row['dateapproved'] ? $row['dateapproved']->format('Y-m-d H:i:s') : ''; $data[] = array( 'details' => '', // 用于渲染详情按钮 'accountcode' => $row['accountcode'], 'accounttitle' => $row['accounttitle'], 'accounttype' => $row['accounttype'], 'tools' => ' <button class="btn btn-default btn-sm view btn-flat" data-id="'.$row['accountcode'].'"><i class="fa fa-eye"></i> View</button> <button class="btn btn-success btn-sm edit btn-flat" data-id="'.$row['accountcode'].'"><i class="fa fa-edit"></i> Edit</button> <button class="btn btn-danger btn-sm delete btn-flat" data-id="'.$row['accountcode'].'"><i class="fa fa-trash"></i> Delete</button> '.($row['approvedby'] ? '' : '<button class="btn btn-warning btn-sm approve btn-flat" data-id="'.$row['accountcode'].'"><i class="fa fa-check-square-o"></i> Approve</button>').' ', // 存储详情需要的数据 'postedby' => $row['postedby'], 'dateposted' => $dateposted, 'approvedby' => $row['approvedby'], 'dateapproved' => $dateapproved ); } echo json_encode(array('data' => $data)); ?>
- 修改DataTables初始化代码,配置AJAX数据源和列渲染规则:
function format ( dataSource ) { var html = '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;" class="table table-bordered">'; for (var key in dataSource){ html += '<tr>'+ '<td>' + key +'</td>'+ '<td>' + dataSource[key] +'</td>'+ '</tr>'; } return html += '</table>'; } $(document).ready(function() { window.earnings_amendment_account_table = $('#earnings_amendment_account').DataTable({ ajax: 'tableBody.php', // 指向返回JSON的后端接口 columns: [ { data: 'details', render: function() { return '<td class="details-control"></td>'; } }, { data: 'accountcode' }, { data: 'accounttitle' }, { data: 'accounttype' }, { data: 'tools' } ], rowCallback: function(row, data) { // 给每行绑定详情需要的数据 $(row).data({ 'key-1': data.postedby, 'key-2': data.dateposted, 'key-3': data.approvedby, 'key-4': data.dateapproved }); } }); // 绑定详情点击事件(这里不需要每次刷新都重新绑定,DataTables会自动维护事件委托) $('#earnings_amendment_account').on('click', 'td.details-control', function () { var tr = $(this).closest('tr'); var row = earnings_amendment_account_table.row(tr); if (row.child.isShown()) { row.child.hide(); tr.removeClass('shown'); } else { row.child(format({ 'Posted By': tr.data('key-1'), 'Date Posted': tr.data('key-2'), 'Approved By': tr.data('key-3'), 'Date Approved': tr.data('key-4') })).show(); tr.addClass('shown'); } }); });
- 最后修改
SubmitFormData的回调,只需要调用DataTables的ajax.reload()即可:
function SubmitFormData() { var add = $("#add").val(); var add_accountcode = $("#add_accountcode").val(); var accounttitle = $("#accounttitle").val(); var accounttype = $("#accounttype").val(); var postedby = $("#postedby").val(); var dateposted = $("#dateposted").val(); $.post("earnings_amendment_account_add.php", { add: add, add_accountcode: add_accountcode, accounttitle: accounttitle, accounttype: accounttype, postedby: postedby, dateposted: dateposted }, function(data) { $('#results').html(data); $('#myForm')[0].reset(); // 直接让DataTables刷新数据,它会自动处理分页、排序等状态 earnings_amendment_account_table.ajax.reload(); }); }
总结
- 如果你想快速修复现有代码,方案一最直接,不需要改动后端逻辑。
- 如果你希望代码更规范、可维护,方案二更推荐——完全利用DataTables的内置功能,从根源上避免手动操作DOM带来的状态不一致问题。
内容的提问来源于stack exchange,提问作者pjustindaryll
相关产品推荐
相关产品推荐

