就我了解的来说,我还是想为这个插件正名 : DataTables 是一个特别强大的插件,它现有的API可以解决我所有的需求,而且异常便捷。
在我们数据量小的情况下 ,配合deferRender(延迟渲染),我们还可以考虑全部加载到浏览器中,在浏览器中实现分页。但是数据量大的时候,我们就不得不使用 服务端分页了。
这篇博文,我们就来说一下,JQuery DataTables 服务端分页的实现。
JS 基本配置 :
基本配置,我在上一篇博文中已经介绍了 JQuery DataTables插件使用说明(最新),在这里我们只介绍一下,服务端分页需要配置的参数。
//基本配置
$.fn.dtconfig = {
"serverSide": true, //开启服务器模式,必须
processing: true, //是否显示加载中提示,可缺省
"paging": false, //关闭本地分页,默认false,可缺省
"pageLength" :10, //每页长度,可缺省
"pagingType": "full_numbers" //分页布局样式,可缺省
}
//配置服务端请求(必须)
$.fn.dtconfig.ajax = {
url: '/UserManage/GetUserList',//请求地址
type: 'Post',// 异步请求方式
data:{},// 请求参数,可为静态参数,亦可谓动态参数
// DataTables类库 很强大,提供了可配置的节点,也就是说,同一种功能,我们可以有多种选择去实现它。data这个参数就是个例子,我们可以使用data参数去设置我们的查询参数,但是查询的时候,是有其他实现方式的。
// 在Data中添加参数后, 如:
data:{"TestID":123}
//testID 这个参数,将直接拼接到 请求表单中,下面我们分析的DataTables 请求表单的时候,会说到这个问题。
};
这样 分页功能,我们就实现了,在我们点击 下一页的时候,插件就会发起一个我们配置好的请求。再配合后端,返回改页数据,我们的分页功能就完成了。
在这里,有一个重点,那就是 DataTables的请求, 下面我跟大家 详细的分析一下 DataTables 的请求表单。
DataTables 的请求表单
这里涉及到一个知识点 ,DataTables 在发起异步请求的时候,有几个重要的参数:
draw,length ,start
/*参数说明*/
// draw 参数
draw: 1 // 这个参数需要 特别注意 ,draw 标识当前的绘制,服务端在接收到这个参数后,需要将这个参数返回,必须返回,而后客服端重新绘制表格后,这个参数会 + 1 ,表示已更新。
@start : int
//请求的起始行(比如:第一页: 0,第二页: 1*pagelength)
@length : int
//每页的长度
@search[value]:string
//:单独要查询的值
@search[regex]: true or false
//是否支持正则
分页后端实现(以ASP.NET MVC 为例)
在处理后端的时候,我利用了一下 “MVC 神奇的模型“,下面就是后端的逻辑,注释我已经写在里面了,不知道大家能不能看懂,我把几个重要的点说一下。
逻辑:
1. 接收DataTables请求参数(DataTableModel 类)
首先,我写了一个 DataTables的参数模型 (详情参考 DataTables 请求表单),我将请求的参数更新到了这个模型里。
2. 将DataTables 里的参数 转换为 查询条件
也就是TryUpdateUserModel的逻辑
3. 使用查询条件进行查询
配合 draw,start,length,还有我们的查询条件,进行分页查询,而后将 总数及当前页数据,返回给客户端
/// <summary>
/// 分页获取用户列表
/// </summary>
/// <param name="form">请求表单</param>
/// <returns></returns>
public ActionResult GetUserList(FormCollection form)
{
//编写一个 DataTables请求的表单模型
DataTableModel inModel = new DataTableModel();
//将请求参数,更新到DataTableModel模型中
if (!TryUpdateModel<DataTableModel>(inModel))
{
//模型绑定失败
inModel.draw = Convert.ToInt32(form["draw"]);//重要参数
inModel.start = Convert.ToInt32(form["start"]);//起始行
inModel.length = Convert.ToInt32(form["length"]);//每页长度
}
//更新查询参数
// 从DataTables 表单模型中,提取出要查询的参数来,放到userModel 查询条件中
User userModel = TryUpdateUserModel(inModel);
//执行分页查询
try
{
int count = 0;
List<User> ds = UserDB.GetUserListByParam(userModel, out count, inModel.start, inModel.length);
return Json(new
{
draw = inModel.draw,//注意这个参数,一定要回传
recordsTotal = count,//这个参数也特别重要,标识了全部数量,有这个参数,客户端才能确定分成多少页
recordsFiltered = count,//过滤查询后的数量
data = ds,// 该页的数据
});
}
catch(Exception e)
{
return Json(new
{
draw = inModel.draw,
error = "加载失败,请重试!"
});
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace UMSystem.Models
{
/// <summary>
/// datatables 组件参数模型(部分)
/// </summary>
[Serializable]
public class DataTableModel
{
/// <summary>
/// 绘制计数器
/// </summary>
public int draw { get; set; }
/// <summary>
/// 起始位置
/// </summary>
public int start { get; set; }
/// <summary>
/// 当前页记录数
/// </summary>
public int length { get; set; }
/// <summary>
/// 各列详情
/// </summary>
public List<ColumnsDetail> columns { get; set; }
/// <summary>
/// 搜索
/// </summary>
public ColumnsSearch search { get; set; }
}
[Serializable]
public class ColumnsDetail
{
public string name { get; set; }
public string data { get; set; }
public bool searchable { get; set; }
public bool orderable { get; set; }
public ColumnsSearch search { get; set; }
}
[Serializable]
public class ColumnsSearch
{
public string value { get; set; }
public bool regex { get; set; }
}
}
/// <summary>
/// 更新查询条件
/// 根据DataTable查询参数
/// </summary>
/// <param name="inModel">DataTable查询参数</param>
/// <returns>用户模型</returns>
private User TryUpdateUserModel(DataTableModel inModel)
{
try
{
User outModel = new User();
foreach (var item in inModel.columns)
{
switch (item.name)
{
case "Name":
outModel.Name = item.search.value;
break;
case "ClassID":
outModel.ClassID =Convert.ToInt32(item.search.value);
break;
}
}
return outModel;
}
catch
{
return new User();
}
}