datatables可以自動幫我們實現分頁,但當數據量過萬時,datatables顯示數據會很慢,因為datatables每取出一條數據,就要創建 tr/td ,所以數據越多,速度就越慢(我5萬條數據大概需要40秒)。
datatables的服務端模式可以解決這個問題。客戶端模式是一次性把數據加載到前台渲染,很耗時間,服務端模式,根據分頁到后台提取相應的數據。
使用服務端模式一般需要配置下面的一些參數,案例:
<!DOCTYPE html> <html> <head> <title>測試datatables服務端</title> <link rel="stylesheet" type="text/css" href="__ADMIN__/css/jquery.dataTables.css"> <!-- jQuery --> <script type="text/javascript" charset="utf8" src="__ADMIN__/js/jquery.js"></script> <!-- DataTables --> <script type="text/javascript" charset="utf8" src="__ADMIN__/js/jquery.dataTables.js"></script> </head> <body> <table id="table_id_example" class="display"> <thead> <tr> <th>user_id</th> <th>username</th> <th>email</th> </tr> </thead> <tbody> <!-- 由datatables自動添加 tr、td --> </tbody> </table> <script> $(document).ready(function() { $("#table_id_example").dataTable({ "lengthMenu": [ [4,8,10,15,20,-1], // 具體的數量 [4,8,10,15, 20,"全部"] // 文字描述 ], "paging": true, // 是否開啟分頁功能(默認開啟) 'info': true, // 是否顯示分頁的統計信息(默認開啟) "searching":true, // 是否開啟搜索功能(默認開啟) "ordering": true, // 是否開啟排序功能(默認開啟) "order":[ [0,'asc'] ], // 設置默認排序的表格列[參數1是表格列的下標,從0開始] "stateSave": true, // 是否保存當前datatables的狀態(刷新后當前保持狀態) "processing": true, // 顯示處理中的字樣[數量多的時候提示用戶在處理中](默認開啟) "serverSide": true, // 是否開啟服務器模式 // false時,會一次性查詢所有的數據,dataTables幫我們完成分頁等。 // true時,點擊分頁頁碼就會每次都到后台提取數據。 "language": //把文字變為中文 { "sProcessing": "處理中...", "sLengthMenu": "顯示 _MENU_ 項結果", "sZeroRecords": "沒有匹配結果", "sInfo": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項", "sInfoEmpty": "顯示第 0 至 0 項結果,共 0 項", "sInfoFiltered": "(由 _MAX_ 項結果過濾)", "sInfoPostFix": "", "sSearch": "搜索:", "sUrl": "", "sEmptyTable": "表中數據為空", "sLoadingRecords": "載入中...", "sInfoThousands": ",", "oPaginate": { "sFirst": "首頁", "sPrevious": "上頁", "sNext": "下頁", "sLast": "末頁" }, "oAria": { "sSortAscending": ": 以升序排列此列", "sSortDescending": ": 以降序排列此列" } }, // 使用ajax到后台服務獲取數據 "ajax": { "url": "{:url('User/index')}", //請求數據的后台地址 "type": "POST", // ajax的請求方法 }, //需要接收返回的數據 //總的數量與表格的列數必須一致,不能多也不能少,一個變量代表一個td //如果data接收服務器沒有返回該字段信息,那么該字段一定要同時設置defaultContent屬性 //例{'data':'a',"defaultContent":""}, "columns": [ {"data": "user_id"}, {"data": "username"}, {"data": "email"}, ] }); }); </script> </body> </html>
上面的設置好之后,給服務端發送ajax請求,我們可以在瀏覽器的控制台看到ajax請求的數據如下:
我們可以在服務端接收這些數據,由於接收到的是一個多維數組,拆分數據的時候注意一下即可。以下是PHP中TP5框架處理服務端數據的案例:
if( request()->isAjax() ){ $this->user = new UserModel; //接收所有傳過來的post數據 $datatables = request()->post(); //得到排序的方式 $order = $datatables['order'][0]['dir']; //得到排序字段的下標 $order_column = $datatables['order'][0]['column']; //根據排序字段的下標得到排序字段 $order_field = $datatables['columns'][$order_column]['data']; //得到limit參數 $limit_start = $datatables['start']; $limit_length = $datatables['length']; //得到搜索的關鍵詞 $search = $datatables['search']['value']; //從數據庫取出結果 //如果有搜索行為,則按照關鍵詞查詢數據 if ($search) { $data = $this->user ->order("$order_field $order") ->limit($limit_start,$limit_length) ->where('user_id','LIKE',"%$search%") ->select(); $data_keyword = $this->user ->where('user_id','LIKE',"%$search%") ->select(); $cnt = count($data_keyword); //獲取滿足關鍵詞的總記錄數 }else{ //沒有關鍵詞,則查詢全部 $data = $this->user ->order("user_id $order") ->limit($limit_start,$limit_length) ->select(); $cnt = $this->user->count(); // 數據總數 } if($data) { $data = collection($data)->toArray(); } $info = [ 'draw'=> request()->post('draw'), // ajax請求次數,作為標識符 'recordsTotal'=>count($data), // 獲取到的結果數(每頁顯示數量) 'recordsFiltered'=>$cnt, // 符合條件的總數據量 'data'=>$data, //獲取到的數據結果 ]; //轉為json返回 return json( $info );
如果不會TP5框架或者使用其他編程語言,這里有通用的思路。
因為現在是后端模式,一些業務邏輯需要我們去處理:
1.從ajax中接收到必要的數據,如果需要用到分頁,需要查數據庫的limit函數的開始、結束參數;要實現排序,則需要獲取排序的字段、排序的方式;要加上搜索功能,就要獲取到搜索的關鍵字。
2.要做是否有搜索行為的判斷,有搜索關鍵字就用到where語句將關鍵字查出,沒有則直接查出返回結果即可。比較直白的邏輯:將這些數據整合到sql查詢語句中,需要排序就用order,需要分頁就加上limit,需要搜索就加where條件判斷
3.由於要返回符合條件的總數量,搜關鍵詞跟查詢所有數據獲得的數據量肯定不同,所以要分來獲取;搜關鍵詞的時候要查詢2次數據庫,一次是查出帶limit的結果,一次是查出帶關鍵詞的結果
4.查關鍵詞不會得到查哪個字段,只能自己通過程序判斷出來,所以最好只查一個字段的關鍵詞
5.最后的返回數據是核心,‘draw’要原樣返回,'data'是從數據庫中獲取到的數據,轉為json格式返回給datatables。
附: