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

AJAX刷新后Client-Side DataTable分页失效(单页显示)修复问询

解决DataTables AJAX刷新后分页失效的问题

这个问题我之前也踩过坑——核心原因是你现在的操作同时混合了手动修改DOM和DataTables自带的AJAX刷新,导致DataTables的内部数据状态和实际DOM不一致,分页、排序这些依赖内部状态的功能自然就失效了。

为什么你的代码会出问题?

你在AJAX提交成功后,先通过$.get替换了#table-body的HTML内容,然后又调用了$("#earnings_amendment_account").DataTable().ajax.reload()。这两步操作完全冲突:

  1. 手动替换DOM会让DataTables丢失对表格数据的控制权,它还停留在初始化时的旧数据状态,根本不知道DOM已经更新了。
  2. ajax.reload()是给配置了ajax数据源的DataTables用的,而你的初始化代码并没有设置这个选项,所以这行代码其实起不到正确的刷新作用,反而会干扰DataTables的状态。

修复方案(两种可选)

方案一:快速适配现有代码,刷新后重新初始化DataTables

这种方式不需要修改后端代码,只需要调整前端的AJAX回调逻辑,让DataTables重新识别新的DOM内容:

  1. 先把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();
});
  1. 修改你的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自己处理数据渲染和状态维护:

  1. 修改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));
?>
  1. 修改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');
    }
  });
});
  1. 最后修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:26:36