凌峰创科服务平台

Datatable服务器分页如何实现高效数据加载?

什么是服务器端分页?

我们要理解客户端分页和服务器端分页的区别:

Datatable服务器分页如何实现高效数据加载?-图1
(图片来源网络,侵删)
  • 客户端分页

    • 工作方式:一次性从服务器获取所有数据(10,000 条),然后在浏览器(客户端)中由 DataTables 插件进行分页、排序和搜索。
    • 优点:实现简单,响应速度快(因为所有操作都在本地)。
    • 缺点:当数据量巨大时(比如超过 1 万条),首次加载会非常慢,消耗大量浏览器内存,甚至可能导致浏览器卡死或崩溃,这是 客户端分页最大的弊端
  • 服务器端分页

    • 工作方式:用户每次翻页、排序或搜索时,DataTables 都会向后端发送一个请求,请求当前页需要的数据,后端根据请求,只查询并返回当前页的数据(每页 10 条,就只查 10 条)。
    • 优点
      1. 加载速度快:首次加载和每次交互都只传输少量数据,页面响应迅速。
      2. 节省带宽:网络传输的数据量小。
      3. 节省服务器资源:数据库查询效率高,只查询需要的数据。
      4. 可处理海量数据:无论数据库中有多少条数据,前端体验都很好。
    • 缺点
      1. 实现复杂:需要后端配合,编写相应的 API 接口。
      2. 依赖网络:每次交互都需要等待服务器响应,可能会有轻微延迟。

当数据量超过几千条时,强烈推荐使用服务器端分页。


如何实现服务器端分页?

实现服务器端分页主要分为三个部分:

Datatable服务器分页如何实现高效数据加载?-图2
(图片来源网络,侵删)
  1. 前端 (HTML + JavaScript):配置 DataTables,启用服务器端模式,并处理从后端返回的数据。
  2. 后端 (API):接收前端请求,解析分页、排序、搜索参数,从数据库查询数据,并按照 DataTables 要求的格式返回。

前端实现

前端的核心是配置 serverSide: true

HTML 结构

<!DOCTYPE html>
<html>
<head>DataTables 服务器端分页示例</title>
    <!-- 引入 DataTables CSS -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2>用户列表</h2>
        <table id="myTable" class="table table-striped table-bordered" style="width:100%">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>姓名</th>
                    <th>邮箱</th>
                    <th>注册日期</th>
                </tr>
            </thead>
            <tbody>
                <!-- 数据将通过 AJAX 动态加载,这里留空 -->
            </tbody>
        </table>
    </div>
    <!-- 引入 jQuery -->
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
    <!-- 引入 Bootstrap JS (DataTables 使用了它的样式) -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <!-- 引入 DataTables JS -->
    <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
    <script>
        $(document).ready(function () {
            $('#myTable').DataTable({
                // 核心配置:启用服务器端模式
                "processing": true, // 显示处理中提示
                "serverSide": true, // 启用服务器端模式
                "ajax": "api/users", // 指定数据源 API 地址
                "columns": [ // 定义列,必须与后端返回的数据结构匹配
                    { "data": "id" },
                    { "data": "name" },
                    { "data": "email" },
                    { "data": "created_at" }
                ],
                "language": { // 中文提示
                    "processing": "加载中...",
                    "lengthMenu": "显示 _MENU_ 条记录",
                    "zeroRecords": "没有匹配结果",
                    "info": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
                    "infoEmpty": "显示第 0 至 0 项结果,共 0 项",
                    "infoFiltered": "(由 _MAX_ 项结果过滤)",
                    "search": "搜索:",
                    "paginate": {
                        "first": "首页",
                        "last": "末页",
                        "next": "下页",
                        "previous": "上页"
                    }
                }
            });
        });
    </script>
</body>
</html>

关键前端配置说明

  • serverSide: true这是最重要的开关,告诉 DataTables 使用服务器端处理。
  • ajax: "api/users":指定获取数据的 URL,当用户与表格交互(翻页、排序、搜索)时,DataTables 会向这个 URL 发送 AJAX 请求。
  • processing: true:在数据加载时,表格下方会显示一个 "Processing..." 的提示,提升用户体验。
  • columns:定义表格的列。data 属性指定该列显示的数据字段名,这个字段名必须与后端返回的 JSON 数据中的键名一致。

后端实现 (以 PHP 为例)

后端需要接收前端发送的参数,进行数据库查询,并返回一个特定格式的 JSON 对象。

DataTables 发送的请求参数

当 DataTables 发送 AJAX 请求时,它会附带以下参数(通过 GET 请求):

  • draw: 一个计数器,用于确保响应是针对哪个请求的,后端原样返回即可。
  • start: 当前页的起始索引(从 0 开始)。
  • length: 每页显示的记录数。
  • search[value]: 全局搜索框的输入内容。
  • order[0][column]: 排序的列索引(从 0 开始)。
  • order[0][dir]: 排序方向,asc (升序) 或 desc (降序)。
  • columns[i][data]: 第 i 列对应的数据字段名。
  • columns[i][searchable]: 第 i 列是否可搜索。
  • columns[i][orderable]: 第 i 列是否可排序。

后端返回的 JSON 格式

后端必须返回一个 JSON 对象,包含以下四个键:

Datatable服务器分页如何实现高效数据加载?-图3
(图片来源网络,侵删)
{
  "draw": 1, // 与请求中的 draw 参数一致
  "recordsTotal": 100, // 数据库中总记录数
  "recordsFiltered": 90, // 经过搜索后,符合条件的总记录数
  "data": [ // 当前页的数据数组
    { "id": 1, "name": "张三", "email": "zhangsan@example.com", "created_at": "2025-01-01" },
    { "id": 2, "name": "李四", "email": "lisi@example.com", "created_at": "2025-01-02" }
  ]
}
  • draw: 客户端请求的次数,服务器端直接返回这个值即可。
  • recordsTotal: 数据库中所有记录的总数,不进行任何过滤。
  • recordsFiltered: 根据客户端的 search 参数过滤后,符合条件的记录总数,如果没有搜索,这个值应该和 recordsTotal 相同。
  • data: 一个数组,包含当前页需要显示的数据,数组的每个元素都是一个对象,其键名必须与前端 columns 中定义的 data 属性一致。

PHP 示例代码 (使用 PDO)

假设我们有一个 users 表。

<?php
// api/users.php
header('Content-Type: application/json');
// --- 1. 连接数据库 ---
$host = 'localhost';
$dbname = 'your_database';
$user = 'your_username';
$pass = 'your_password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// --- 2. 获取 DataTables 发送的参数 ---
$draw = $_GET['draw'] ?? 1;
$start = $_GET['start'] ?? 0;
$length = $_GET['length'] ?? 10;
$search = $_GET['search']['value'] ?? '';
$orderColumnIndex = $_GET['order'][0]['column'] ?? 0;
$orderDir = $_GET['order'][0]['dir'] ?? 'asc';
// 定义列名映射
$columns = ['id', 'name', 'email', 'created_at'];
$orderColumn = $columns[$orderColumnIndex];
// --- 3. 构建基础 SQL 查询 ---
// 先计算总记录数
$totalRecordsQuery = "SELECT COUNT(*) FROM users";
$stmt = $pdo->query($totalRecordsQuery);
$totalRecords = $stmt->fetchColumn();
// 计算过滤后的记录数
$filteredRecordsQuery = "SELECT COUNT(*) FROM users WHERE 1=1";
$params = [];
if (!empty($search)) {
    $filteredRecordsQuery .= " AND (name LIKE :search OR email LIKE :search)";
    $params[':search'] = "%$search%";
}
$stmt = $pdo->prepare($filteredRecordsQuery);
$stmt->execute($params);
$filteredRecords = $stmt->fetchColumn();
// --- 4. 构建数据查询 SQL ---
$dataQuery = "SELECT id, name, email, created_at FROM users WHERE 1=1";
if (!empty($search)) {
    $dataQuery .= " AND (name LIKE :search OR email LIKE :search)";
    // 重新绑定参数,因为要复用
    $params = [':search' => "%$search%"];
}
$dataQuery .= " ORDER BY $orderColumn $orderDir";
$dataQuery .= " LIMIT :start, :length";
$stmt = $pdo->prepare($dataQuery);
$params[':start'] = (int)$start;
$params[':length'] = (int)$length;
$stmt->execute($params);
$data = $stmt->fetchAll();
// --- 5. 返回 JSON 响应 ---
echo json_encode([
    "draw" => intval($draw),
    "recordsTotal" => intval($totalRecords),
    "recordsFiltered" => intval($filteredRecords),
    "data" => $data
]);
exit;
?>

实现 DataTables 服务器端分页的关键在于:

  1. 前端:设置 serverSide: trueajax URL,并正确定义 columns
  2. 后端
    • 正确解析 DataTables 发来的分页、排序、搜索参数。
    • 根据这些参数动态构建 SQL 查询。
    • 返回包含 draw, recordsTotal, recordsFiltered, data 四个键的 JSON。

遵循这个模式,你就可以在任何后端语言(如 Node.js, Python, Java, C# 等)中实现高效、可扩展的服务器端分页功能。

分享:
扫描分享到社交APP
上一篇
下一篇