jquery.dataTables的摸索之路-服務端分頁配置
最近閒來無事想研究下資料表格,因為之前接觸過layui和bootstrap的資料表格,本著能學多少學多少的學習態度,學習下dataTables的服務端分頁配置。特與同學們一塊分享下從中遇到的問題和解決方式。
與bootstrap的資料表略有不同,在引入相關js後除了必要的DOM節點(<table id="table" class="table table-responsive table-hover"></table>)外我們還需要表頭部分,具體就是bootstrap的整張表格都可以通過js渲染,而dataTables的表頭部分需要我們自己在頁面新增,就像下面這樣:
<table id="table" class="table table-responsive table-hover"> <thead> <tr> <th>ID</th> <th>檔名稱</th> <th>檔案型別</th> <th>邏輯地址</th> <th>實體地址</th> <th>更新人</th> <th>更新時間</th> </tr> </thead> </table>
我以為dataTable的服務端分頁會像bootstrap一樣,給他一串url,剩下的交給他,於是我寫了如下程式碼進行表格的初始化工作:
<script type="text/javascript" src="static/assets/js/jquery-2.1.0.min.js"></script> <script type="text/javascript" src="static/assets/libs/datatablejs/jquery.dataTables.min.js"></script>
<script type="text/javascript"> initTable(); function initTable() { var 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": "末頁"}}; $('#table').DataTable({ 'processing': true, 'pageLength': 5, // 每頁顯示條數 'ajax': '/admin/file/list', //非同步請求地址 'lengthChange': false, 'searching': false, 'info': true, 'autoWidth': false, //自動列寬 language: language, //國際化 columns: [{ data: "id" //繫結後臺資料列屬相 }, { data: "filename" }, { data: 'filetype', defaultContent: "" //預設值 }, { data: 'logicadress', defaultContent: "" }, { data: 'physicsadress', defaultContent: "" }, { data: 'modifyUser', defaultContent: "-" }, { data: 'modifyTime', defaultContent: "" }], columnDefs: [{ //自定義首列複選框 targets: [0], //第幾列:預設從0開始 orderable: false, // 是否支援排序 render: function (id, type, row, meta) { return '<input type="checkbox" name="ids" value=' + id + '><label for="input-' + id + '"></label>'; } }] }) } </script>
重新整理頁面結果如下:
咦!!我的資料哪去啦?難道是請求除了問題?
檢視控制檯,發現請求沒問題後臺資料也正常接收。
對了,服務端返回資料的格式有問題!!後臺資料返回的是自定義JSON,不符合dataTables的預設值規範!!
{"code":"200",
"msg":null,
"data":{
"count":7,
"totalPage":2,
"pageSize":5,
"currentPage":1,
"list":[
{"createUser":null,"createTime":"2019-05-28T14:24:56.000+0000","modifyUser":10000001,"modifyTime":"2019-05-09T14:24:59.000+0000","id":7,"filename":"女王大人","filetype":3,"logicadress":"www","physicsadress":"E:/test.txt","sort":"99"},
{"createUser":null,"createTime":"2019-05-28T14:24:54.000+0000","modifyUser":10000001,"modifyTime":"2019-05-08T14:25:02.000+0000","id":6,"filename":"你的皇帝","filetype":2,"logicadress":"www","physicsadress":"E:/test.txt","sort":"99"},
{"createUser":null,"createTime":"2019-05-28T14:24:51.000+0000","modifyUser":10000001,"modifyTime":"2019-05-07T14:25:04.000+0000","id":5,"filename":"阿里斯嘉","filetype":0,"logicadress":"www","physicsadress":"E:/test.txt","sort":"99"},
{"createUser":null,"createTime":"2019-05-28T14:24:49.000+0000","modifyUser":10000001,"modifyTime":"2019-05-06T14:25:07.000+0000","id":4,"filename":"馬大哈","filetype":1,"logicadress":"www","physicsadress":"E:/test.txt","sort":"99"},
{"createUser":null,"createTime":"2019-05-28T14:24:46.000+0000","modifyUser":10000001,"modifyTime":"2019-05-05T14:25:09.000+0000","id":3,"filename":"土豆司","filetype":1,"logicadress":"www","physicsadress":"E:/test.txt","sort":"99"}
],
"sort":null,
"order":null
}
}
我在服務端封裝了返回的資料,導致dataTables不知道從哪下手!
在找到問題所在後,結合百老師的各種部落格找到了解決的辦法:改造‘ajax’屬性
$('#table').DataTable({ ... 'ajax': { url: '/admin/file/list', dataSrc: function (json) { return json.data.list; //指定返回資料列的位置,該資料列為陣列形式 } }, ... })
通過指定資料列的位置,可以實現對後臺自定義資料的渲染(通常情況下會保證返回資料的統一格式):
再次重新整理頁面資料能正常顯示了
嗯,很滿意。。但新的問題又出現了:分頁出毛病了,再檢視控制檯發現我一共有7條記錄,按理說應該是2頁7條
通過百老師的大量部落格,發現了問題所在:未開啟服務端分頁!!
繼續改造如下:
$('#table').DataTable({ ... 'serverSide': true, // 開啟服務端分頁 ... )}
再次重新整理頁面,意外發生了,很突然:
出現了意想不到的事情:在開啟真正的服務端分頁後,我的資料又丟了!!
這次是後臺的錯誤,通過控制檯可以發現在開啟服務端分頁後,dataTables在初始化時向後臺傳遞了很多引數:
可以看到url後面拼接了一連串的字串,導致後臺的SpringMVC在封裝引數時出現了問題:
@GetMapping("file/list") public RestJson page(PageHelper pageHelper) { System.out.println(pageHelper); RestJson json = fileRecordService.getFileRecordByPage(pageHelper); return json; }
PageHelper是我自定義的分頁工具類具體程式碼如下:
public class PageHelper<T> implements Serializable { private Integer count;//總記錄數 private Integer totalPage;//總頁數 private Integer pageSize;//每頁顯示的條數 private Integer currentPage;//當前頁 private List<T> list = new ArrayList<T>();//分頁之後的資料 private String sort;//排序欄位 private String order;//升序或降序 public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } public Integer getTotalPage() { return totalPage; } public void setTotalPage(Integer totalPage) { this.totalPage = totalPage; } public Integer getPageSize() { return this.pageSize == null ? 5 : this.pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public Integer getCurrentPage() { return this.currentPage == null ? 1 : this.currentPage; } public void setCurrentPage(Integer currentPage) { this.currentPage = currentPage; } public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; } public String getSort() { return this.sort == "" ? null : this.sort; } public void setSort(String sort) { this.sort = sort; } public String getOrder() { return this.order == "" ? null : this.order; } public void setOrder(String order) { this.order = order; } /** * 計算總頁數 * * @return 總頁數 */ public int countPage() { int countPage = getCount() / getPageSize(); return getCount() % getPageSize() == 0 ? countPage : countPage + 1; } /** * 從哪條開始取(當前記錄數) * * @return 當前記錄數 */ public int countOffSet() { return getPageSize() * (getCurrentPage() - 1); } /** * MYSQL * 取幾條 * * @return 取幾條 */ public int countMySQLLength() { return getPageSize(); } /** * ORACLE * 取幾條 * * @return 取幾條 */ public int countOracleLength() { return getPageSize() * getCurrentPage(); } @Override public String toString() { return "[ " + "count:" + count + " totalPage:" + totalPage + " pageSize:" + pageSize + " currentPage:" + currentPage + " sort:" + sort + " order:" + order + " ]"; } }
由於SpringMVC封裝引數時出現了問題,於是我想能不能在dataTables初始化時自定義後臺傳遞的引數呢?
繼續改造‘ajax’屬性:
$('#table').DataTable({ ... 'ajax': { url: '/admin/file/list', // url請求 data: function (data) { // 定義初始化引數 :data為向後臺傳送的引數obj return $.extend( {},{}, { //自定義引數 "currentPage": data.start/data.length+1, //當前頁"pageSize": data.length, // 每頁顯示條數,data.length='pageLength'屬性的值 我設定的是5 } ) }, dataSrc: function (json) { return json.data.list; } }, ... )}
再次重新整理頁面,資料又回來了
等等,分頁是怎麼回事??不打緊,加上這兩句:
$('#table').DataTable({ ... 'ajax': { ... dataSrc: function (json) { json.recordsFiltered = json.data.count; // 指定記錄數 json.recordsTotal = json.data.totalPage; // 指定頁數 return json.data.list; } }, ... })
再次重新整理頁面出現了預期的結果:
除錯完畢,發現部分列不應該排序,檢視‘columnDefs’屬性,發現ID列排序被禁用,但排序圖示初始化時依然存在。
新增如下屬性:
$('#table').DataTable({ ... 'order': [1,'asc'], //修改預設的排序列為第2列、升序 ... })
再次重新整理頁面後正常顯示,能不能實現指定列排序呢?
修改程式碼如下(為了使程式碼更簡潔我將‘columnDefs’屬性中的程式碼轉移到‘columns’屬性中):
$('#table').DataTable({ ... columns:[{ // 合併後的columns data: "id", // 繫結後臺資料列的屬性 sortable: false, // 禁止排序 render : function(id, type, row, meta) { // 將資料進行DOM轉換 return '<input type="checkbox" name="ids" value=' + id + '><label for="input-' + id + '"></label>'; } },{ data: "filename", render : function(id) { return '<a href="javascript:;">'+id+'<a/>'; } },{ data: 'filetype', defaultContent : "", sortable: false, },{ data: 'logicadress', defaultContent : "", sortable: false, },{ data: 'physicsadress', defaultContent : "", sortable: false, },{ data: 'modifyUser', defaultContent : "-", sortable: false, },{ data: 'modifyTime', defaultContent : "" }],
... })
重新整理頁面後效果如下:
點選排序發現沒有反應。後臺的排序已經實現了,前臺只要傳送相應的引數即可。
繼續修改程式碼如下:
$('#table').DataTable({ ... 'ajax': { ... data: function (data) { console.log(data); return $.extend( {},{}, { "currentPage": data.start/data.length+1, "pageSize": data.length, "order": data.order[0].dir, //升序或降序:隨滑鼠點擊發生變化 "sort": data.order[0].column==1?"fileName":"modifyTime" //獲取排序列:下標從0開始,1代表第二列(因為只有兩列參與排序,所以簡單寫了) } ) }, ... }, ... })
重新整理頁面,開啟控制檯,我們看下‘data’的結構:
{ "draw": 1, "columns": [ { "data": "id","name": "","searchable": true,"orderable": false, "search": {"value": "", "regex": false} }, ... ], "order": [{"column": 1,"dir": "asc"}], "start": 0, "length": 5, "search": {"value": "","regex": false} }
一個標準的json物件,現在回頭看看這兩行程式碼是不是有種恍然大悟的感覺:
"order": data.order[0].dir, "sort": data.order[0].column==1?"fileName":"modifyTime"
後臺的分頁和排序程式碼無須贅述,本文主要是分享在使用dataTables時如何自定義前後臺引數問題,其實使用起來和bootstrap的資料表格有很多相似的地方,感覺還是後者更簡單一些。鹹魚水平,不足之處歡迎指