1. 程式人生 > >jquery.dataTables的摸索之路-服務端分頁配置

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的資料表格有很多相似的地方,感覺還是後者更簡單一些。鹹魚水平,不足之處歡迎指