数据表 - 如何在页面加载时仅加载一定数量的行?

Posted

技术标签:

【中文标题】数据表 - 如何在页面加载时仅加载一定数量的行?【英文标题】:Datatables - How to load only a certain amount rows on page-load? 【发布时间】:2017-01-04 00:34:59 【问题描述】:

我有一个 fiddle 可以对 URL 进行 ajax 并呈现一个表格,但我想在页面加载期间延迟并仅加载 10 行。

html

<table id="example" class="display" cellspacing="0" >
    <thead>
        <tr>
            <th>Account ID</th>
            <th>Name</th>
            <th>Email</th>
        </tr>
    </thead>
</table>

JS

$(document).ready(function() 

$('#example').DataTable( 
        "bPaginate": true,
        "processing": true,
        "bServerSide": true,

        ajax: 
            url: 'https://api.myjson.com/bins/1egsx',
            dataSrc: 'data'
        ,
        columns: [
             data: 'account_id' ,
             data: 'name' ,
             data: 'email' 
        ],
        "deferRender": true,
        "deferLoading": 10,

     );

);

我一直得到

没有找到匹配的记录

【问题讨论】:

你的意思是iDisplayLength 我的意思是deferLoadingiDisplayLength 会做什么? iDisplayLength 只显示所需的行数 我认为@DestinatioN 明白了。 【参考方案1】:

TL;DR:您可能应该将deferRender 与客户端处理一起使用在没有deferRender 的情况下使用服务器端处理(通过修复您的 JSON 数据)。此答案假定您需要服务器端处理。

延迟加载

正确使用服务器端处理时,默认行为是每个 ajax 请求只发送一页上的行数。您不需要使用 deferLoading - 这就是它的作用(来自documentation here):

在使用服务器端处理时,DataTables 的默认操作模式是简单地丢弃表中当前存在的所有数据,并向服务器发出请求以获取要显示的第一页数据。这对于一个空表来说很好,但是如果您已经将第一页数据显示在纯 HTML 中,那就浪费了资源。因此,此选项的存在允许您指示 DataTables 不发出初始请求,而是使用页面上已有的数据(不会对其应用排序等)。

由于您的所有数据都来自 ajax,因此不应选择该选项。

deferRender

如果您正确使用服务器端处理,您也确实不需要使用deferRenderdeferRender 将(来自documentation here):

作为一个帮助说明这一点的示例,如果您加载一个包含 10,000 行的数据集,但分页显示长度仅为 10 条记录,而不是创建所有 10,000 行,则启用延迟呈现时,DataTables 将仅创建 10 条记录。

注意这里的重要短语:

如果您加载包含 10,000 行的数据集

如果您正确使用服务器端处理,您应该只在一次加载中加载每页的行数。 deferRender 确实是在使用客户端处理时加快数据表的一个选项。服务器端处理已经处理了deferRender 所做的事情。有关如何加快数据表的速度,请参阅 DataTables FAQ 中的这张图片:

请注意,它强调deferRender 仅用于客户端。这里要注意的是,如果您没有很多行(数万以上),您可能不需要使用服务器端处理。

正确使用服务器端处理:

您的问题可能来自这样一个事实,即您的 API 没有为服务器端处理返回正确的 JSON 格式;您需要发送的信息不仅仅是要显示的数据。这是带有完整描述的documentation page(您绝对应该阅读它),但我将尝试在下面概述基础知识。

请求

发送到您的 API 的请求将包含一些您需要处理的数据。

draw 是跟踪请求-响应对集合的唯一标识符;响应中的值需要与请求中的值匹配。这就是数据表将请求与响应相匹配的方式。

start 表示应该在响应中的第一个记录;如果我们每页显示 10 条记录并且我们在第 2 页,start 将等于 10,因此在响应中我们只发送编号为 10-19 的记录。

length 表示此次抽奖的预期行数,因此在上面第 2 页每页 10 条记录的示例中,length 将等于 10。这是您应该返回的记录数。该值将基于 Datatables 初始化的 lengthMenupageLength 选项。 (分别记录在 here 和 here)

要记住但经常被遗忘的重要事情是只发送与length 一样多的行;不要在第一个请求中发送所有行。

回应

您的回复也需要更改。 基本上,您需要返回一个类似于以下示例的对象(来自 documentation page),而不是只返回 data


    "draw": 1,
    "recordsTotal": 57,
    "recordsFiltered": 57,
    "data": [
        [
            "Angelica",
            "Ramos",
            "System Architect",
            "London",
            "9th Oct 09",
            "$2,875"
        ],
        [
            "Ashton",
            "Cox",
            "Technical Author",
            "San Francisco",
            "12th Jan 09",
            "$4,800"
        ],
        ...
    ]

除了通常的data 之外,请注意其他数据:drawrecordsTotalrecordsFiltered。这些是使用服务器端处理时的必需选项。

draw 代表对您的 API 发出的请求对应的编号; GET 请求也将有一个draw 值,并且 GET 中的值必须与响应中的值匹配。

recordsTotal表示表中的记录总数,跨所有页面,其中recordsFiltered表示满足GET请求设置的过滤要求的记录数(如果没有过滤,应该等于到recordsTotal

这些是您回复的最低要求元素,但您应该查看链接文档以获取有关可选值的更多信息。

旁注

作为旁注;如果您使用的是 DataTables 1.10 或更高版本,bServerSide 应该是 serverSidebPaginate 应该是 paging

【讨论】:

【参考方案2】:

您也可以使用iDisplayLength

$('#example').DataTable( 
        "aLengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
        "iDisplayLength": 10,
        "bPaginate": true,
        "processing": true,
        "bServerSide": true,

        ajax: 
            url: 'https://api.myjson.com/bins/1egsx',
            dataSrc: 'data'
        ,
        columns: [
             data: 'account_id' ,
             data: 'name' ,
             data: 'email' 
        ],

     );

【讨论】:

【参考方案3】:

我假设您的意图是在页面加载后立即显示 DataTable。下面描述了两种加载部分数据的方法,具体取决于您的要求。整个数据可以在稍后的时间点通过触发诸如单击按钮之类的事件来加载。在这两种情况下,整个数据也将被下载并存储在本地,然后可以根据触发的事件进行加载,以避免再次调用来获取整个数据。

案例一:只想从源头下载部分数据

在 DataTable 处理数据之前,将从“https://api.myjson.com/bins/1egsx”获取整个数据。如果您只想从 URL 中获取部分数据,您可以创建您的自定义函数,该函数将以 AJAX 交互模式 (readyState=3) 解析数据,在收到前 10 个条目后停止,然后处理数据并将其作为DataTable 的输入数据。以下是您需要做的总结

var inputData = '';
function loadDataTablePreview() 
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() 
    if (this.readyState == 3 && this.status == 200) 
        inputData += this.responseText;
        // Count the number of closing ''. If its 10, lets start processing our data
        // Get the index of 10 closing ''
        // Create a substring of inputData
        // append ']'
        // Now JSON Decode
        var decodedData = JSON.parse(inputData);
        // Now create an instance of the DataTable passing this data as the input data 
        $('#example').DataTable( 
          "bPaginate": true,
          "processing": true,
          "bServerSide": true,
          data: decodedData,
          columns: [
             data: 'account_id' ,
             data: 'name' ,
             data: 'email' 
          ],
        );
    
    else if (this.readyState == 4 && this.status == 200) 
       // JSON Decode the data and store it to load later
    
  ;
  xhttp.open("GET", "https://api.myjson.com/bins/1egsx", true);
  xhttp.send();


$(document).ready(function() 
  loadDataTablePreview();

案例2:下载完整数据后只加载前10个条目

假设您可以下载整个数据,在显示 DataTable 之前,您可以为 dataSrc 创建一个函数,如下所示。这将显示仅返回表中的 10 个条目。您可以选择将整个 JSON 存储在浏览器数据存储(如 sessionStorage)中的此函数中,然后触发 JS 函数在稍后的时间点加载整个 JSON。

$(document).ready(function() 

  $('#example').DataTable( 
    "bPaginate": true,
    "processing": true,
    "bServerSide": true,
    ajax: 
        url: 'https://api.myjson.com/bins/1egsx',
        dataSrc: function ( json ) 
                    // Store entire data in sessionStorage
                    // return the first 10 entries only for now
                    return json.data.slice(0,10);
                 ,
    ,
    columns: [
         data: 'account_id' ,
         data: 'name' ,
         data: 'email' 
    ],
  );
);

【讨论】:

以上是关于数据表 - 如何在页面加载时仅加载一定数量的行?的主要内容,如果未能解决你的问题,请参考以下文章

如何每页加载一定数量的对象?

如何使用 volley 下载一定数量的 JSON

如何在收到一定数量的数据后调用 Web 服务并将其加载到表格视图中

如何在单击时仅重新加载一个 div?

在单页应用程序中,当在 VueJs 中输入新数据时,如何在不重新加载页面的情况下重新加载 api [关闭]

在购物车页脚中重新加载 PHP If/Else 语句而不重新加载整个页面? ( XT 浮动车)