Datatables是一款很便捷,功能很强大的前端分页插件。但是,在实际应用中,表格通常数据量会非常庞大,所以不提倡把数据一次性加载到页面。所以,datatables使用后台分页是一个不错的选择。但是,使用后台分页就要放弃datatables自带的3个功能:排序,分页条数选项,内容搜索。因为采用后端分页后,这三项内容都必须由后端完成(目前因为本人能力有限,只完成了分页和内容搜索,排序网上也有其他人做过,有心人不妨试成功了跟我说一下)。
本人用过amazeui的datatables插件,也使用过原生datatables及其提供的bootstrap风格。两者其实一样。只是amazeui的datatables帮你汉化完和引入了amazeui的table风格。这里不再详述要引用的css和js,具体可以百度。
首先讲讲如何使用datatables的汉化。
$('#dimtable').DataTable({
"searching" : false,//关闭自带搜索
"bLengthChange" : false,//关闭自带分页选项
"ordering" : false,//关闭排序
"serverSide" : true,//这个用来指明是通过服务端来取数据
"processing" : true, //打开数据加载时的等待效果
"oLanguage" : {
"sLengthMenu" : "每页显示 _Menu_条记录",
"sInfo" : "当前显示_START_到_END_条,共_TOTAL_条记录",
"sInfoEmpty" : "显示第 0 至 0 项结果,共 0 项",
"sZeroRecords" : "对不起,查询不到相关的数据",
"sInfoFiltered" : "",//"(从 _MAX_ 条记录过滤)"此项为显示过滤信息
"oPaginate" : {
"sFirst" : "首页",
"sPrevious" : "上一页",
"sNext" : "下一页",
"sLast" : "尾页"
},
"sSearch" : "查找"},
});
});
你需要定义一个table,及其表头。同时,可以通过控制th的宽度控制表格宽度。接下来,我们通过id给这个table绑定datatables。
<table width="100%" class="am-table am-table-compact am-table-striped tpl-table-black" id="list">
<thead>
<tr>
<th style="display:none">ID</th>
<th style="width:50%">地址</th>
<th style="width:20%">坐标</th>
<th style="width:30%">操作</th>
</tr>
</thead>
<tbody>
<!-- more data -->
</tbody>
</table>
接下来,我们开始第一种后台分页的方法。这种方法目前暂不支持自定义刷新,仅点击分页信息时会向后台请求数据。具体实现如下代码。
var datatable
$(function(){
datatable=$('#list').DataTable({
"searching": false,
"bLengthChange": false,
"ordering": false,
"serverSide": true,//这个用来指明是通过服务端来取数据
"sAjaxSource": "#(ctx)/admin/getHouseInfo",//这个是请求的地址
"fnServerData": retrieveData, // 获取数据的处理函数
"columns" : [ //处理行数据,这里的data数量必须与<th>的数量一致,否则报错。同时,function中的data包含整行数据信息
{ data : "id","visible" : false },
{ data : function(data, type, full){
return data.province+data.city+data.county+data.address;
}},
{ data : function(data, type, full){
return "("+data.ax+","+data.ay+")";
}},
{
data : function(data, type, full){
return "<div class=\"tpl-table-black-operation\">"+
"<a href=\"javascript:;\"><i class=\"am-icon-pencil\"></i> 修改</a>"+
"<a href=\"javascript:;\"><i class=\"am-icon-pencil\"></i> 管理</a>"+
"<a href=\"javascript:;\" class=\"tpl-table-black-operation-del\"><i class=\"am-icon-trash\"></i> 删除</a></div>";
}}
]
});
});
function retrieveData(sSource,aoData, fnCallback) {
$.ajax({
url : sSource,//这个就是请求地址对应sAjaxSource
data : {"aoData":JSON.stringify(aoData)},//这个是把datatable的一些基本数据传给后台,比如起始位置,每页显示的行数
type : 'post',
dataType : 'json',
async : false,
success : function(result) {
fnCallback(result);//把返回的数据传给这个方法就可以了,datatable会自动绑定数据的
},
error : function(msg) {
//报错执行方法
}
});
}
此时后台接收到的请求JSON信息为:
aoData=[{"name":"sEcho","value":1},
{"name":"iColumns","value":4},
{"name":"sColumns","value":",,,"},
{"name":"iDisplayStart","value":0},
{"name":"iDisplayLength","value":10},
{"name":"mDataProp_0","value":"id"},
{"name":"mDataProp_1","value":"name"},
{"name":"mDataProp_2","value":"disname"},
{"name":"mDataProp_3","value":"function"}]
其中,有用的信息为sEcho(不知道为什么,就是有用),iDisplayStart:请求数据的初始位,IDisplayLength为每页行数。本人默认使用10行分页,有需要的人可以自行提取次数据。本人后台方法(JFinal)如下,SpringMvc差不多,参考一下就行:
public void getHouseInfo(){
Map<String, Integer> map = DataTableUtil.getPageNo(getPara("aoData"));
Page<House> list = houseService.pageHouse(map.get("iDisplayStart")/10+1, 10);//因为datatables请求后台只提供请求初始位置信息(如10个分页,那第一页请求信息为0,第二页为10,第三页为20)。这个方法是JFinal的分页方法,第一个参数为页数,第二个参数为每页行数。若不按10条分页,请提取IDisplayLength参数,替换数据10。
renderJson(DataTableUtil.dataType(list, map.get("sEcho")));
}
private static Map<String, Integer> map = new HashMap<>();
private static JSONObject getObj = new JSONObject();
//提取JSON数据中有用的信息
public static Map<String, Integer> getPageNo(String json){
JSONArray jsonarray = JSONArray.parseArray(json);
for (int i = 0; i < jsonarray.size(); i++) {
JSONObject obj = (JSONObject) jsonarray.get(i);
if (obj.get("name").equals("sEcho"))
map.put("sEcho", Integer.parseInt(obj.getString("value")));
if (obj.get("name").equals("iDisplayStart"))
map.put("iDisplayStart", Integer.parseInt(obj.getString("value")));
}
return map;
}
//回传数据信息,需按照datatables的数据格式返回信息
public static <E> String dataType(Page<E> page,Integer pageNum){
List<E> list = page.getList();
getObj.put("sEcho", pageNum);// 不知道这个值有什么用,有知道的请告知一下
getObj.put("iTotalRecords", list.size());//每页行数
getObj.put("iTotalDisplayRecords",page.getTotalRow());//分页的总行数
getObj.put("aaData", list);//分页信息
return getObj.toString();
}
接下来我们说第二种分页方法,这种分页方法比较好用,支持随意向后台传递自定义数据,并支持手动刷新datatables。代码如下:
var datatable
$(function(){
datatable=$('#list').DataTable({
"searching": false,
"bLengthChange": false,
"ordering": false,
"serverSide": true,//这个用来指明是通过服务端来取数据
"processing": true, //打开数据加载时的等待效果
"ajax":{
"url": "#(ctx)/admin/getHouseInfo",
"type":"post",
"data": function ( d ) {
var level1 = $('#search').val(); //此处为外部搜索框信息
//添加额外的参数传给服务器
d.extra_search = level1;
return {"aoData":JSON.stringify(d)};
}
},
"columns" : [
{ data : "id","visible" : false },
{ data : function(data, type, full){
return data.province+data.city+data.county+data.address;
}},
{ data : function(data, type, full){
return "("+data.ax+","+data.ay+")";
}},
{
data : function(data, type, full){
return "<div class=\"tpl-table-black-operation\">"+
"<a href=\"javascript:;\"><i class=\"am-icon-pencil\"></i> 修改</a>"+
"<a href=\"javascript:;\"><i class=\"am-icon-pencil\"></i> 管理</a>"+
"<a href=\"javascript:;\" class=\"tpl-table-black-operation-del\"><i class=\"am-icon-trash\"></i> 删除</a></div>";
}}
]
});
});
//搜索框的搜索按钮点击事件。其它地方想刷新datatables直接使用里面的方法就好。
$("#searchBtn").on('click',function(){
datatable.ajax.reload();
});
此时,后台接收到的JSON信息与第一个方法完全不一样:
aoData={"draw":1,
"columns":[{"data":"id","name":"","searchable":true,"orderable":false,"search"{"value":"","regex":false}},{"data":"function","name":"","searchable":true,"orderable":false,"search":{"value":"","regex":false}},{"data":"function","name":"","searchable":true,"orderable":false,"search":{"value":"","regex":false}},{"data":"function","name":"","searchable":true,"orderable":false,"search":{"value":"","regex":false}}],
"order":[],
"start":0,
"length":10,
"search":{"value":"","regex":false},
extra_search":""}
可以看到有用信息为start(初始位置),length(每页长度),extra_search(额外传送参数)。
所以,本人的JFinal后台如下写:
public void getHouseInfo(){
Map<String, Integer> map = DataTableUtil.getPageNoAjax(getPara("aoData"));
Page<House> list = houseService.pageHouse(map.get("iDisplayStart")/10+1, 10);
renderJson(DataTableUtil.dataTypeAjax(list));
}
private static Map<String, Integer> map = new HashMap<>();
private static JSONObject getObj = new JSONObject();
//目前我是按照10行分页,有需要的按照其他行数分页的请提取参数length
public static Map<String, Integer> getPageNoAjax(String json){
JSONObject jobject = JSONObject.parseObject(json);
map.put("iDisplayStart", Integer.parseInt(jobject.getString("start")));
return map;
}
//返回数据,与第一种返回数据格式不一样
public static <E> String dataTypeAjax(Page<E> page){
List<E> list = page.getList();
getObj.put("iTotalRecords", list.size());//每页的行数
getObj.put("iTotalDisplayRecords",page.getTotalRow());//分页总行数
getObj.put("aaData", list);//分页内容信息
return getObj.toString();
}
本人写的SpringMvc后台如下:
@RequestMapping("getHouseInfo")
@ResponseBody
public DataTableViewPage<House> getPageList(String aoData) {
Map<String, Object> param = houseservice.getExtraParam(aoData);//获取相关参数
String search = (String) param.get("extra_search");//获取搜索框参数
Pageable pageable = houseservice.getPageable(aoData);//获取分页信息
Page<House> housepage = null;
if (search.isEmpty())
housepage = houseservice.getAllHouse(pid,pageable);
else
housepage = houseservice.getHouseBySearch(search, pageable);
return new DataTableViewPage<House>((int) housepage.getTotalElements(), housepage.getSize(), housepage.getContent());
}
//获取参数
@Override
public Map<String, Object> getExtraParam(String json) {
Map<String, Object> map = new HashMap<String, Object>();
JSONObject jo = JSONObject.parseObject(json);
map.put("extra_search", jo.getString("extra_search"));
return map;
}
//获取分页信息
@Override
public Pageable getPageable(String json) {
JSONObject jo = JSONObject.parseObject(json);
int pageNo = jo.getIntValue("start") / 10;
Pageable pageable = new PageRequest(pageNo, 10);
return pageable;
}
//返回数据类型DataTableViewPage
public class DataTableViewPage<T> {
private List<T> aaData;
private Integer iTotalDisplayRecords;
private Integer iTotalRecords;
public DataTableViewPage(Integer iTotalDisplayRecords,Integer iTotalRecords,List<T> aaData){
this.aaData = aaData;
this.iTotalDisplayRecords=iTotalDisplayRecords;
this.iTotalRecords = iTotalRecords;
}
public List<T> getAaData() {
return aaData;
}
public void setAaData(List<T> aaData) {
this.aaData = aaData;
}
public int getiTotalDisplayRecords() {
return iTotalDisplayRecords;
}
public void setiTotalDisplayRecords(int iTotalDisplayRecords) {
this.iTotalDisplayRecords = iTotalDisplayRecords;
}
public int getiTotalRecords() {
return iTotalRecords;
}
public void setiTotalRecords(int iTotalRecords) {
this.iTotalRecords = iTotalRecords;
}
}