如何从在线JSON分批加载DataTable数据,优化大数据集加载速度?
问题描述
通过在线URL加载JSON数据到DataTable,当数据量超过10000行时,表格加载耗时超30秒。虽然已设置分页(每页仅显示十余条),但因预先加载全量数据集导致加载缓慢。希望实现仅加载当前页所需数据,无需等待全量数据加载完成;同时保留搜索、筛选交互功能,用户操作后默认显示第一页结果。曾尝试用Ajax实现,但未能适配该在线JSON资源。
原代码
JavaScript
const url = 'https://raw.githubusercontent.com/________________.json'; async function populate() { const response = await fetch(url); const evidenceData = await response.json(); console.log(evidenceData) // Build Table function buildTable(data) { var table = document.getElementById('myTable') table.innerHTML = data.map(function(row) { let [country, title, category, date, link, image] = row; return `<tr> <td> <br><br> <a href="${link}" target='_blank'> <img class="tableThumbnail" src=${image}><br><br> </td></a> <td> <span class="tableTitle"><br><br><a href="${link}" target='_blank'>${title}</a><br></span> </td> <td>${country}</td> <td>${category}</td> <td>${date}</td> </tr>`; }).join(''); } $(document).ready(function() { var oTable = $('.mydatatable').DataTable({ "dom": "<<t>ip>", "columnDefs": [{ targets: [2, 3, 4], visible: false, searchable: true, }] }); $('#searchInput').keyup(function() { oTable.search($(this).val()).draw(); }); }) buildTable(evidenceData) } populate();
HTML
<head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <!-- Datatables --> <link rel="stylesheet" href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css"> <script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script> </head> <body> <form class="form"> <div> <input type="text" id="searchInput" class="form-control" placeholder=" Search"> </div> </form> <div class="main"> <table class="table mydatatable" id="mydatatable"> <thead> <tr> <th> </th> <th> </th> <th> </th> <th> </th> </tr> </thead> <tbody id="myTable"> </tbody> </table> </div> </body>
解决方案
由于你的JSON是静态在线资源,没有后端接口支持分页和搜索参数,所以需要前端模拟服务器端处理逻辑,结合DataTables的serverSide模式实现按需加载。核心思路是:先一次性获取全量数据(仅请求一次),之后所有分页、搜索、排序操作都在前端对全量数据进行过滤和截取,避免重复请求。
修改后的代码
JavaScript
const url = 'https://raw.githubusercontent.com/________________.json'; let fullData = []; // 存储全量数据,仅加载一次 $(document).ready(function() { // 先加载全量数据,再初始化表格 fetch(url) .then(response => response.json()) .then(data => { fullData = data; initDataTable(); }) .catch(err => console.error('数据加载失败:', err)); function initDataTable() { $('.mydatatable').DataTable({ dom: "<<t>ip>", serverSide: true, // 开启服务器端模式 pageLength: 10, // 每页显示10条,可调整 columnDefs: [{ targets: [2, 3, 4], visible: false, searchable: true, }], columns: [ // 定义列的渲染逻辑,对应数据中的字段位置 { data: null, render: function(row) { const [, , , , link, image] = row; return `<br><br><a href="${link}" target='_blank'><img class="tableThumbnail" src="${image}"><br><br></a>`; } }, { data: null, render: function(row) { const [, title, , , link] = row; return `<span class="tableTitle"><br><br><a href="${link}" target='_blank'>${title}</a><br></span>`; } }, { data: 0 }, // country { data: 2 }, // category { data: 3 } // date ], // 自定义Ajax处理逻辑,模拟服务器端分页/搜索 ajax: function(data, callback, settings) { let filteredData = [...fullData]; // 处理搜索 if (data.search.value) { const searchTerm = data.search.value.toLowerCase(); filteredData = filteredData.filter(row => { // 搜索所有可见+可搜索列:country、title、category、date return row[0].toLowerCase().includes(searchTerm) || row[1].toLowerCase().includes(searchTerm) || row[2].toLowerCase().includes(searchTerm) || row[3].toLowerCase().includes(searchTerm); }); } // 处理分页:截取当前页数据 const startIndex = data.start; const endIndex = startIndex + data.length; const paginatedData = filteredData.slice(startIndex, endIndex); // 返回DataTables所需的格式 callback({ draw: data.draw, recordsTotal: fullData.length, recordsFiltered: filteredData.length, data: paginatedData }); }, // 搜索后自动回到第一页 search: { return: true } }); // 绑定自定义搜索框事件 $('#searchInput').keyup(function() { $('.mydatatable').DataTable().search($(this).val()).draw(false); }); } });
HTML(无需修改,保持原结构即可)
<head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <!-- Datatables --> <link rel="stylesheet" href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css"> <script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script> </head> <body> <form class="form"> <div> <input type="text" id="searchInput" class="form-control" placeholder=" Search"> </div> </form> <div class="main"> <table class="table mydatatable" id="mydatatable"> <thead> <tr> <th> </th> <th> </th> <th> </th> <th> </th> </tr> </thead> <tbody id="myTable"> </tbody> </table> </div> </body>
关键说明
- 一次性加载全量数据:页面初始化时仅请求一次JSON资源,之后所有操作都基于内存中的全量数据,避免重复请求。
- 开启serverSide模式:让DataTables认为数据来自服务器,触发分页、搜索时调用自定义的
ajax函数。 - 前端模拟服务器逻辑:在
ajax函数中完成搜索过滤、分页截取,返回符合DataTables格式的数据。 - 搜索后回到第一页:通过
search.return: true确保搜索操作后自动跳转到第一页。 - 列渲染优化:直接在DataTables的
columns配置中定义渲染逻辑,替代原有的buildTable函数,更贴合DataTables的工作流。
内容的提问来源于stack exchange,提问作者kodikai
相关产品推荐
相关产品推荐

