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()
參考——重要程度由高到低:
2. 引導我作demo的文章 jQuery Data Tables 插件自定義Ajax分頁實現
一臉懵時能夠作一個demo,後端數據返回,form完成,再一步步作轉移。