php 如何在pageload上从表中加载一定数量的行,并且仅在用户加载行时才加载更多的行?

u2nhd7ah  于 2022-12-10  发布在  PHP
关注(0)|答案(2)|浏览(200)

我有一个使用DataTables的表,它包含大量的行,因此这会导致页面加载非常缓慢,因为我假设浏览器会等待表被填充后才显示页面。
我希望只加载表的一个页面(10行),并且只在用户浏览表时显示进一步的数据,显示加载标志也很好。
我研究并听说过一个名为“deferRender”的DataTables函数,它应该可以完成我所需要的任务,但我无法让它与我的表一起工作。
我的表有8列+html是使用PHP生成的,它从文本文件中的数据构建表:

<?php

     $tdcount = 1; $numtd = 8; // number of cells per row
     $str = "<table id=\"table1\" class=\"table1 table table-striped table-bordered\">
                                     <thead>
                                     <th>1</th>
                                     <th>2</th>
                                     <th>3</th>
                                     <th>4</th>
                                     <th>5</th>
                                     <th>6</th>
                                     <th>7</th>
                                     <th>8</th>
                 </thead>
                                     <tbody>

 ";
     $f = fopen("tabledata.txt", "r");
     if ( $f === FALSE ) {
 exit;
    }
     while (!feof($f)) {
         $arrM = explode(",",fgets($f));
         $row = current ( $arrM );
         if ($tdcount == 1)
             $str .= "<tr>"; $str .= "<td>$row </td>";
         if ($tdcount == $numtd) {
             $str .= "</tr>";
             $tdcount = 1;
         } else {
             $tdcount++;
         }
     }
     if ($tdcount!= 1) {
         while ($tdcount <= $numtd) {
             $str .= "<td>&nbsp;</td>"; $tdcount++;
         } $str .= "</tr>";
     }
     $str .= "</tbody></table>";
     echo $str;

然后使用以下代码将其转换为数据表:

<script>
        $(document).ready(function() {
        $('#table1').basictable({
          forceResponsive: false
          });
        $('#table1').DataTable( { "order": [[ 0, "desc" ]] } );

          });

</script>

我已经阅读了这里的说明:https://datatables.net/examples/server_side/defer_loading.html,并知道需要将参数添加到JS:

"processing": true,
"serverSide": true,
"ajax": "scripts/server_processing.php",
"deferLoading": 57

和使用server_processing脚本,但是这个例子只展示了如何在连接到DB时使用它,而不是在使用php从文本文件加载数据时。
我怎样才能做到这一点呢?

txu3uszq

txu3uszq1#

这将完全集中在“服务器端”解决方案的DataTables方面。如何编写支持它所需的服务器端逻辑超出了这个答案的范围。但我希望这些注解至少能澄清该逻辑需要是什么,以及如何处理它。
假设
假设您有一个包含1,000个数据列的文字档(或一百万个数据列,但太多数据列无法同时传送到浏览器和DataTable)。这个文字档是简单的垂直缐分隔档案,包含三个字段:

id|name|description
1|widget_1|This is a description for widget 1
2|widget_2|This is a description for widget 2
3|widget_3|This is a description for widget 3
...
1000|widget_1000|This is a description for widget 1000

您希望使用服务器端处理一次向DataTable发送10个项。
您的数据Map到一个简单的JSON结构,如下所示-一个对象数组(每个对象是一条记录):

[
    {
        "id": 1,
        "name": "widget_1",
        "description": "This is a description for widget 1"
    },
    {
        "id": 2,
        "name": "widget_2",
        "description": "This is a description for widget 2"
    },
    ... // more records...
]

数据表定义

您的数据表定义如下所示--在此阶段,它特意非常简单:

<body>

<div style="margin: 20px;">

<table id="demo" class="display dataTable cell-border" style="width:100%">
</table>

</div>

<script type="text/javascript">

  $(document).ready(function() {
    $('#demo').DataTable({
      serverSide: true,
      ajax: {
        url: 'http://localhost:7000/data',
        type: 'POST'
      },
      columns: [
        { title: 'ID',
          data: 'id' },
        { title: 'Name',
          data: 'name' },
        { title: 'Description',
          data: 'description' }
      ]
    });

  });
</script>

</body>

初始响应

第一次显示网页时,它将向URL(http://localhost:7000/data)发送初始POST请求,并期望从Web服务器接收JSON响应,其中包含要显示的数据。
因为DataTables使用serverSide: true,所以DataTables将期望JSON具有特定的结构,如此处所述。
具体来说,服务器必须将所有必需字段(drawrecordsTotalrecordsFiltereddata)添加到它发送给DataTable的JSON中。
在我们的例子中,它看起来像这样-注意,它只是我们前面提到的JSON结构,添加了一些额外的元数据字段:

{
    "draw": 1,
    "recordsTotal": 1000,
    "recordsFiltered": 1000,
    "data": [{
        "id": 1,
        "name": "widget_1",
        "description": "This is a description for widget 1"
    }, {
        "id": 2,
        "name": "widget_2",
        "description": "This is a description for widget 2"
    }, {
        "id": 3,
        "name": "widget_3",
        "description": "This is a description for widget 3"
    }, {
        "id": 4,
        "name": "widget_4",
        "description": "This is a description for widget 4"
    }, {
        "id": 5,
        "name": "widget_5",
        "description": "This is a description for widget 5"
    }, {
        "id": 6,
        "name": "widget_6",
        "description": "This is a description for widget 6"
    }, {
        "id": 7,
        "name": "widget_7",
        "description": "This is a description for widget 7"
    }, {
        "id": 8,
        "name": "widget_8",
        "description": "This is a description for widget 8"
    }, {
        "id": 9,
        "name": "widget_9",
        "description": "This is a description for widget 9"
    }, {
        "id": 10,
        "name": "widget_10",
        "description": "This is a description for widget 10"
    }]
}

服务器负责构建这个JSON -服务器数据集的前10条记录。服务器还告诉DataTable它总共有1,000条记录,并且它还没有过滤掉任何数据-因此过滤后总共也有1,000条记录。
DataTables需要所有这些信息,因此它知道要显示多少个分页按钮,以及要显示哪些分页数据。
请注意,完成所有这些工作完全是服务器的责任-这就是为什么它被称为“服务器端”处理。
客户端(浏览器)只有10条记录需要呈现--因此这一过程很快。

(我刚刚注意到屏幕截图提到了“500条记录”--这是我的服务器端代码中的一个错误--没有过滤器,所以我需要修复它)。

后续请求

当用户单击页面导航按钮(例如,页面“4”)时,将触发从DataTables到服务器的新请求。DataTables使用此处描述的字段自动生成此请求。
请求作为表单数据发送。
在我们的示例中,请求如下所示:

"Form data": {
    "draw": "5",
    "columns[0][data]": "id",
    "columns[0][name]": "",
    "columns[0][searchable]": "true",
    "columns[0][orderable]": "true",
    "columns[0][search][value]": "",
    "columns[0][search][regex]": "false",
    "columns[1][data]": "name",
    "columns[1][name]": "",
    "columns[1][searchable]": "true",
    "columns[1][orderable]": "true",
    "columns[1][search][value]": "",
    "columns[1][search][regex]": "false",
    "columns[2][data]": "description",
    "columns[2][name]": "",
    "columns[2][searchable]": "true",
    "columns[2][orderable]": "true",
    "columns[2][search][value]": "",
    "columns[2][search][regex]": "false",
    "order[0][column]": "1",
    "order[0][dir]": "asc",
    "start": "30",
    "length": "10",
    "search[value]": "",
    "search[regex]": "false"
}

这些字段告诉服务器它需要知道的一切,以便它可以准备正确的响应。
在我们的示例中,最重要的字段包括:

"start": "30",
"length": "10"

从第30行开始,提供10条记录。
同样,服务器负责准备一个准确反映所请求数据的JSON响应。
在我们的例子中,这意味着服务器需要有逻辑来读取文本文件到正确的起始点(数据行31 -记住偏移从零开始),总共10行(行31到40)。
上面DataTables请求中的其他字段描述了如何对数据进行排序和筛选。在我们的示例中,没有筛选器"search[value]": "",-数据将按第一列以升序排序。

最终注解

我特意没有叙述以下几点:
1)服务器端代码如何处理发送回DataTable的JSON响应的创建;
2)服务器端程式码如何剖析从DataTable接收的表单要求。
这完全取决于您的服务器端技术。DataTables并不关心这些。它只是传递JSON消息-它与服务器端实现分离-正如它应该做的那样。
关于here中描述的“defer render”选项,如果您觉得需要的话,可以选择添加一个增强功能。

xlpyo6sf

xlpyo6sf2#

不特别与任何语言相关,但我使用Node.js作为示例,为上面解释的内容创建一个最小工作项目:
数据:(将其放在node.js服务工作目录的根目录下)

[ { "id": 1,
    "name": "widget_1",
    "description": "This is a description for widget 1"
},{ "id": 2,
    "name": "widget_2",
    "description": "This is a description for widget 2"
},{ "id": 3,
    "name": "widget_3",
    "description": "This is a description for widget 3"
},{ "id": 4,
    "name": "widget_4",
    "description": "This is a description for widget 4"
},{ "id": 5,
    "name": "widget_5",
    "description": "This is a description for widget 5"
},{ "id": 6,
    "name": "widget_6",
    "description": "This is a description for widget 6"
},{ "id": 7,
    "name": "widget_7",
    "description": "This is a description for widget 7"
},{ "id": 8,
    "name": "widget_8",
    "description": "This is a description for widget 8"
},{ "id": 9,
    "name": "widget_9",
    "description": "This is a description for widget 9"
},{ "id": 10,
    "name": "widget_10",
    "description": "This is a description for widget 10"
},{ "id": 11,
    "name": "widget_11",
    "description": "This is a description for widget 11"
},{ "id": 12,
    "name": "widget_12",
    "description": "This is a description for widget 12"
},{ "id": 13,
    "name": "widget_13",
    "description": "This is a description for widget 13"
},{ "id": 14,
    "name": "widget_14",
    "description": "This is a description for widget 14"
},{ "id": 15,
    "name": "widget_15",
    "description": "This is a description for widget 15"
},{ "id": 16,
    "name": "widget_16",
    "description": "This is a description for widget 16"
},{ "id": 17,
    "name": "widget_17",
    "description": "This is a description for widget 17"
},{ "id": 18,
    "name": "widget_18",
    "description": "This is a description for widget 18"
},{ "id": 19,
    "name": "widget_19",
    "description": "This is a description for widget 19"
},{
    "id": 20,
    "name": "widget_20",
    "description": "This is a description for widget 20"
}]

HTML:(将其置于your working directory/public下)

<!DOCTYPE html>
<html>

<body>
</head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.1/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.js"></script>
</head>

<div style="margin: 20px;">
    <div id = 'pageinfo' style='display:none'></div>
    <table id="demo" class="display dataTable cell-border" style="width:100%"></table>
</div>

<script type="text/javascript">
  $(document).ready(function() {
    var table = $('#demo').DataTable({
      serverSide: true,
      ajax: {
        url: 'http://localhost:3000/data',
        data: $('#pageinfo').text(), //post pagination parameters to server
        type: 'POST'
      },
      columns: [
        { title: 'ID',
          data: 'id' },
        { title: 'Name',
          data: 'name' },
        { title: 'Description',
          data: 'description' }
      ],
      lengthMenu: [5, 10, 20],
      pageLength: 5
    });
    function getinfo(){
        var info = table.page.info();
        return info;
    }
    $('.dataTables_wrapper').on('click',function(e){
        var info = table.page.info();
        $('#pageinfo').text(JSON.stringify(info)) //get the pagination parameters
    })
  });
</script>

</body>
<html>

而服务器:

const fs = require('fs');
const data = JSON.parse(fs.readFileSync("data.json", 'utf8'));

var express = require('express');
var app = express();
var bodyParser = require('body-parser')
app.use( bodyParser.json() );       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
}));

app.use('/static', express.static(__dirname + '/public')); //directory for static html docs
app.post('/data', function(req, res){
    var resp = {"recordsTotal": 20,"recordsFiltered": 20,"start":0,"length":5}
    if(req.body.start){
        resp.draw = JSON.parse(req.body.draw);
        resp.data = data.slice(JSON.parse(req.body.start),
                                JSON.parse(req.body.start)+JSON.parse(req.body.length));
    }else{
        resp.draw = 1;
        resp.data = data.slice(resp.start,resp.start+resp.length);
    }
    res.end(JSON.stringify(resp))
})

app.listen(3000, function () {
    console.log('listening on port 3000');
});

然后,您就可以启动服务器,并在http://localhost:3000/static/dtable.html处浏览结果
通读这些代码,或者深入研究一些中间输出,您将更好地了解DataTable如何在最小的服务器端处理设置下工作。

相关问题