datatables後端分頁

0x01 原因javascript

 


 

平時較少涉及前端,此次本覺得模板中有表單,分頁跳轉搜索功能都比較齊全,能夠高枕無憂,可是細看模板中的分頁跳轉是不須要與後臺交互的,數據一次性寫在前端,再有前端插件完成分頁。css

這種方式確定是不可行的,此次要作的能夠看作資產管理,服務器+主機量級很大,一個機器生成一條 <th>,第一次請求的前端代碼怕是要崩掉。html

因此合理採用的仍是後端分頁前端

 

0x02 分頁方式java

 


 

團隊項目裏看過的幾種後端分頁方式:jquery

1. Paginator + render渲染整個頁面,這種方式比較好理解,可是每一次跳轉分頁,都會替換掉整塊main-content部分。web

2. datatables 後端分頁,這種方式按照datatables提供的API填寫相關信息與邏輯,缺點是ajax

  1) 受限於這種插件的條條框框,要自定義一些內容有點麻煩。 數據庫

    好比原始datatables中search是實時的,即在search input框中輸入 "123",會進行 "1"、"12"、"123"三次過濾,在後端分頁中,就會發起三次查詢。json

    因此要自定義搜索,可是form部分是由datatables初始化過程當中生成的,找半天沒有找到插入自定義<input>框的接口。因此用jquery遍歷再添加 <input>。

 

  2) 文檔不太清晰

    各類API、接口,在文檔中找來找去挺麻煩的。等到整塊寫的差很少的時候,才意外看到官方後端分頁的文檔。

3. 本身編寫form、跳轉、查詢、排序、每頁數量等功能,就是稍顯麻煩,但仍是挺靈活的。

 

0x03 datatables後端分頁流程

 


 

因爲模板自己的表單是基於datatables的,因此最後仍是修改了datatables。

datatables後端分頁的流程大概能夠分爲四部分:

1. 修改datatables的初始化參數,改成後端分頁,並修改其餘設置

2. datatables傳遞數據給服務端

3. 接收服務端數據,好比說取到第10頁的10條json數據

4. 數據渲染至datatables當前頁面

 

0x04 修改datatables初始化參數

 


 

<script type="text/javascript">
    $(function () {
        //提示信息
        var lang = {
            "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": "末頁",
                "sJump": "跳轉"
            },
            "oAria": {
                "sSortAscending": ": 以升序排列此列",
                "sSortDescending": ": 以降序排列此列"
            }
        };

        //初始化表格
        var table = $("#dynamic-table").dataTable({
            language:lang,  //提示信息
            autoWidth: false,  //禁用自動調整列寬
            stripeClasses: ["odd", "even"],  //爲奇偶行加上樣式,兼容不支持CSS僞類的場合
            processing: true,  //隱藏加載提示,自行處理
            serverSide: true,  //啓用服務器端分頁
            searching: false,  //禁用原生搜索
            orderMulti: false,  //啓用多列排序
            order: [],  //取消默認排序查詢,不然複選框一列會出現小箭頭
            renderer: "bootstrap",  //渲染樣式:Bootstrap和jquery-ui
            pagingType: "simple_numbers",  //分頁樣式:simple,simple_numbers,full,full_numbers
            columnDefs: [{
                "targets": 'nosort',  //列的樣式名
                "orderable": false    //包含上樣式名‘nosort’的禁止排序
            }]
        }).api();//此處需調用api()方法,不然返回的是JQuery對象而不是DataTables的API對象
    });
</script>

datatables初始化中,以字典的形式將初始化信息傳遞進去。

其中,language爲表單的一些提示信息。這裏比較簡單,基本上看看就明白。

因此,如今表單已經初始化成了後端模式了。

接下來,怎麼給後端傳遞數據

 

0x05 先後端數據交互

 


 

須要增長的兩個值:ajax 與 column

<script type="text/javascript">
    $(function () {
        //提示信息
        var lang = {
            "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": "末頁",
                "sJump": "跳轉"
            },
            "oAria": {
                "sSortAscending": ": 以升序排列此列",
                "sSortDescending": ": 以降序排列此列"
            }
        };

        //初始化表格
        var table = $("#dynamic-table").dataTable({
            language:lang,  //提示信息
            autoWidth: false,  //禁用自動調整列寬
            stripeClasses: ["odd", "even"],  //爲奇偶行加上樣式,兼容不支持CSS僞類的場合
            processing: true,  //隱藏加載提示,自行處理
            serverSide: true,  //啓用服務器端分頁
            searching: false,  //禁用原生搜索
            orderMulti: false,  //啓用多列排序
            order: [],  //取消默認排序查詢,不然複選框一列會出現小箭頭
            renderer: "bootstrap",  //渲染樣式:Bootstrap和jquery-ui
            pagingType: "simple_numbers",  //分頁樣式:simple,simple_numbers,full,full_numbers
            columnDefs: [{
                "targets": 'nosort',  //列的樣式名
                "orderable": false    //包含上樣式名‘nosort’的禁止排序
            }],
 ajax: function (data, callback, settings) {
                //封裝請求參數
                console.log(data);
                var param = {};
                param.limit = data.length;//頁面顯示記錄條數,在頁面顯示每頁顯示多少項的時候
                param.start = data.start;//開始的記錄序號
                param.page = (data.start / data.length)+1;//當前頁碼
                param.order = data.order[0]
                //console.log(param);
                //ajax請求數據
                $.ajax({
                    type: "GET",
                    url: "http://your_server",
                    cache: false,  //禁用緩存
                    data: param,  //傳入組裝的參數
                    dataType: "json",
                    success: function (result) {
                        console.log(result);
                        //setTimeout僅爲測試延遲效果
                        setTimeout(function () {
                            //封裝返回數據
                            var returnData = {};
                            returnData.draw = data.draw;//這裏直接自行返回了draw計數器,應該由後臺返回
                            returnData.recordsTotal = result.total;//返回數據所有記錄
                            returnData.recordsFiltered = result.total;//後臺不實現過濾功能,每次查詢均視做所有結果
                            returnData.data = result.data;//返回的數據列表
                            //console.log(returnData);
                            //調用DataTables提供的callback方法,表明數據已封裝完成並傳回DataTables進行渲染
                            //此時的數據需確保正確無誤,異常判斷應在執行此回調前自行處理完畢
                            callback(returnData);
                        }, 200);
                    }
                });
            },
            //列表表頭字段
            columns: [
                { "data": "ip" },
                { "data": "online_state" },
                { "data": "machine_id" },
                { "data": "location" },
                { "data": "agent_state" },
                { "data": "system" } ]         }).api();//此處需調用api()方法,不然返回的是JQuery對象而不是DataTables的API對象
    });
</script>

1. ajax: function(data,callback,settings){}——data

data爲datatables自己會提供的數據集合,包含每一列的信息、一頁的數據量(一頁幾行)、查找的值、當前頁等,另外根據datatables的初始化選擇還會包含其餘內容,好比,當點擊排序時,data中將包含排序的列、方式。

想要傳遞給服務端的數據,能夠在這一處取。可是最好將數據從新封裝一遍再發送給服務器,緣由是:

  1) 有的數據是不須要的,好比在原生搜索關閉的狀況下,data中仍是會之後search的信息

  2) 有一些自定義的信息,好比自定義搜索框,能夠封裝入其中再傳給服務器

  3) 整理格式,好比 排序數據 order中, order[0] 包含排序的列和方式,其餘沒什麼用,因此取出order[0] 封裝再發送,簡潔得多。

數據封裝完畢,則採用ajax的方式將數據發送給服務端。

 

2. ajax: function(data,callback,settings){}——callback

callback爲返回給datatables渲染當前表單的數據,以字典形式。

其中,draw與data中的draw相同。

recordsTotal、recordsFiltered填寫爲數據庫總數據量便可,datatables從中獲取數據總量、分頁數量等。

渲染的核心數據 data,是給表單渲染內容用的。

 

3. columns字段

columns字段的做用是:

將回調函數中的data中的數據,按columns的排序渲染入表單列中,好比這裏,第一列爲ip,則將data['ip'] 放到第一列中,以此類推。

 

4. 後端返回什麼數據

後端的數據能夠根據傳遞給回調函數的數據進行猜想拼接,可是data也是字典格式的,返回的數據用Python能夠寫爲:

data = [
    {'ip':'192.168.1.91','online_state':'運行中','machine_id':'91','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.92','online_state':'運行中','machine_id':'92','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.93','online_state':'運行中','machine_id':'93','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.94','online_state':'運行中','machine_id':'94','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.95','online_state':'運行中','machine_id':'95','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.96','online_state':'運行中','machine_id':'96','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.97','online_state':'運行中','machine_id':'97','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.98','online_state':'運行中','machine_id':'98','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.99','online_state':'運行中','machine_id':'99','location':'58security','agent_state':'OK','system':'windows'},
    {'ip':'192.168.1.100','online_state':'運行中','machine_id':'100','location':'58security','agent_state':'OK','system':'windows'},
]
response = {'data':data,'limit':10,'page':10,'total':100}
return JsonResponse(response)

在 ajax success中接收這些數據,再進行封裝、傳入datatables回調函數,從而完成渲染。

其中,顯而易見,data以 「字段」:"內容"的形式存在於字典中。

 

5. 自定義搜索(version2)

(上一次寫的太醜了)

由此,基本已經完成。

可是原生的搜索是不能用了,因此要自定義搜索。

也找不到添加 <input>框的接口,因此,用jquery遍歷搜索再添加<input>元素、綁定事件。

綁定的事件要作什麼事呢?

最簡單的就是讓datatables執行一次提交ajax,這裏使用 datatables對象的draw()函數。

JS代碼:

function search(){
table.draw();
}
var search_input = $('#search_input_html').text();
$("#dynamic-table_wrapper").find(".row").first().find(".col-sm-6").last().append(search_input);
$('#searcy_type').html($('#search_type').text());
$("#search_button").click(function(){
search();
});
$("#search_key").keydown(function(e){
if(e.keyCode == 13){
search();
}
})

 其中插入的代碼用textarea包裹起來,再用val取代碼

<!--ADDING HTML start-->
<textarea id="search_input_html" style="display:none">
    <div class="my_dataTables_filter">
        <div class="span6">
            <select id="searcy_type" class="search_type">
            <select>
            <input id="search_key" class="search_space"></input>
            <button type="button" id="search_button" class="search_button btn">搜索</button>
        </div>
    </div>
</textarea>
<textarea id="search_type" style="display:none">
                <option value="ip">ip</option>
                <option value="online_status">online_status</option>
                <option value="machine_id">machine_id</option>
</textarea>
<!--ADDING HTML end-->

樣式CSS:

.my_dataTables_filter {
    float: right;
}

.search_space{
    height:34px;
    position: relative;
    top:2px;
    left:4px;
}

.search_button{
    width: 50px;
    height: 34px;
    color: #fff;
    /*font-size:20%;*/
    letter-spacing: 1px;
    background: #65CEA7;
    border-bottom: 2px solid #65CEA7;
    /*background: #3385ff;*/
    /*border-bottom: 2px solid #2d78f4;*/
    outline: medium;
    -webkit-appearance: none;
    -webkit-border-radius: 0;
}

.search_type{
    height:34px;
    position: relative;
    top:2px;
    left:4px;
}

 

在初始化結束後,加入這段JS代碼(HTML寫在content部分;CSS放在.css中):遍歷、添加元素、綁定事件、事件爲datatables發出ajax。

draw()默認參數爲true,代表刷新時會跳轉到第一頁從新刷新;draw(false) 則保持在原頁。

同時,搜索的值也要傳遞給服務端:在封裝數據時加入

param.search_key = $("#search_key").val()

 

 

 

參考——重要程度由高到低:

1. datatables服務端處理-可做後端分頁文檔

2. 引導我作demo的文章 jQuery Data Tables 插件自定義Ajax分頁實現

一臉懵時能夠作一個demo,後端數據返回,form完成,再一步步作轉移。

3. 自行封裝請求和返回數據的零耦合服務端分頁

4. 官方文檔 datatables Ajax

5. dataTables-使用詳細說明

相關文章
相關標籤/搜索