项目中用到了Pagination分页栏插件.很精简的一个插件,但是只提供分页栏显示的功能.
如果使用ajax来翻页的话,用起来不太方便.所以打算自己扩展下,前台做的少,js不太好,欢迎大家指点 :-)
例如: 如下使用
$("#pagination_div").pagination(totalSize, {callback:function(nextIndex){
$.ajax({ type : "POST", url : "http://www.baidu.com", data : {page:(nextIndex+1), rows:"10"},
success : function(html) {
$("#page_table_tbody").html("").append(html);
}
});
}}
这样每个用到分页的地方都需要写一次ajax请求,而且返回的html数据需要在后台处理好,如果是json数据的还需要自己去处理,挺麻烦的.
而且现在经常会出现这种情况,后台的分页方法只有一个,返回json数据,然后需要用到的地方解析json,展示哪些属性由前端渲染界面的时候来决定. 所以为了少点重复劳动, 对它扩展了一下.
原本是打算直接改Pagination源码的,但是感觉不太好,一个是怕改出问题,影响到原来已经使用了的地方,一个是升级啥的比较麻烦(虽然感觉这个插件应该不会升级了:-) ). 所以后面决定在另外的js文件中实现功能,然后通过callback将他们两者联系起来.
先说说大概思路:
1.解析json数据和dom的操作属于重复劳动,需要抽象出来.
那么如何抽象出来呢? 列和后台对象的属性如何Mapping起来, 用过JQuery EasyUI的人都知道,它的表格初始化的时候都需要将列的显示名, 对应后台哪个属性(简单的说就是哪一列显示哪个属性)等等的配置在组件初始化的时候传入.
这里我也是使用的这种方法.于是我们写table的时候需要加上一些配置信息,例如:
<table id="table_id">
<thead head>
<tr>
<th name="id">主键</th>
<th name="name">姓名</th>
<th name="link">操作</th>
</tr>
</thead>
<tbody data></tbody>
</table>
这个时候,th的name属性值,就对应着后台对象的属性
好了,现在映射对应起来,但是还有些问题, 很多情况下,表格中都包含一列,用来放按钮,链接等东西,而这些东西并不是后台的属性,而是通过后台属性动态生成的数据. 这个时候怎么办呢? 而且我们经常有的需求就是对日期,金钱等的格式化等等操作.
很容易想到的就是在处理后台json数据的时候回调一下用户定义的函数. 那么有哪些地方需要回调呢?
1.每一行(tr)生成后. 2.每一个单元格(td)完成后. 3.ajax网络错误处理回调. 4.全部处理完成回调 5.单击回调......
如果要做的很灵活的话,就要有很多回调的地方,但是现在项目需求并不是很复杂....提供1,2,3,4的功能就好...其他的有需求了再加,原理是一样的,就是在配置的时候提供回调函数,然后在对应的地方回调.
回调的需要注意的是this对象的使用.如果碰到古怪的问题了,往这方面想象(-.-)
好了,现在要将回调传给我们的组件,我们才能回调到~~! 其他的回调都好说,在初始化组件的时候传进去就好, 但是每一个单元格(td)的回调,就不太好传了..........后面想了个蛋疼的办法 如下面代码所示:
<th name="link" opts="{handler:function(index, data, td){
var a = $('<a>查看</a>');
a.attr('href',' + data.id);
a.appendTo(td);
}}">操作</th>
有点蛋疼,不过没办法...毕竟对于我现在的项目来说,这个情况少,哈哈哈哈哈哈哈,要不做成初始化的时候传也行.
这里handler函数的 index表示当前是第几行, data是后台数据的json对象(某一行的), td是td标签对应的JQuery对象在最后我们会将td这个对象appendTo(tr).
那么怎么将这些配置给初始化到我们的组件中呢? 我的做法:
$.PageProcesser = function(tableId, url, pageSize, opts){
var that = this;
this.tableId = tableId;//table的id,必须的
this.url = url; //ajax请求数据的url必须的
this.pageSize = pageSize ? pageSize : 10; //每页显示条数
if(!tableId || !url){
throw "PageProcesser : the param tableId and url are required";
}
//初始化参数,rowHandler是每行处理完后的回调函数,参数和上面说的类似,提供一个默认配置
//param参数是为了这种情况:ajax请求的时候有其他的请求参数.....
this.opts = jQuery.extend({
param:{},
rowHandler:function(index, data, tr){return true;},},
opts||{}
);
//这个是初始化每一类的配置,包括列对应的属性名,列的位置(1,2,3,4,5),列的处理回调函数
//因为上面td的配置方式,所以这里用eval了,求勿喷 :-)
this.tdOpts = [];
$("#" + tableId + " th[name]").each(function(index, element){
var fieldName = $(this).attr("name");
var fieldOpts = $(this).attr("opts");
fieldOpts = fieldOpts ? eval("fieldOpts = " + fieldOpts) : {};
fieldOpts = jQuery.extend({handler:function(index, data, td){return true;}}, fieldOpts);
that.tdOpts.push({name:fieldName, index:index, opts:fieldOpts});
});
};
好了,现在构造函数定义好了. 初始化类似于这样:
//第一个参数是table的id, 第二个:ajax请求路径,
var pageHaper = new $.PageProcesser("table", "${path}/json", 100, {
param:{type:"1"}, //ajax请求附带的参数
rowHandler:function(index, data, tr){//行处理回调
index % 2 == 0 ? tr.css("color", "red") : "";
}
});
好了,参数定义及初始化都好了,现在来定义方法. 如下代码:
$.extend($.PageProcesser.prototype, {
callback:function(page_index, pagination){//代理pagination的回调函数
this.requester(page_index); //ajax请求函数
return false;
},
requester:function(page){//ajax请求数据
var requestParam = jQuery.extend({page:(page+1), rows:this.pageSize}, this.opts.param); //注意设置context:this 防止ajax回调函数中this调用不到handlerJson方法.
$.ajax({ type : "POST", url : this.url, data : requestParam, context:this,
success : function(json) {
this.handlerJson(json);
}
});
},
handlerJson:function(json){//根据后台json和配置更新dom
var datas = json ? (json.rows ? json.rows : []) : [] ;
var tbody = $("#" + this.tableId + " tbody[data]");
tbody.html("");//清空原来的数据
for(var i=0 ; i<datas.length ; i++){//循环json中的数组,创建tr,td,并调用对应的回调
var tr = $("<tr></tr>");
for(var j=0 ; j<this.tdOpts.length ; j++){
var val = datas[i][this.tdOpts[j].name];
var td = $("<td></td>").text(val);
this.tdOpts[j].opts.handler(i, datas[i], td);//回调列处理器
td.appendTo(tr);//这里可以写成批量的方式来提高效率....
}
this.opts.rowHandler(i, datas[i], tr);//回调用户行处理器
tr.appendTo(tbody);//这里也可以写成批量的方式来提高效率....
}
},
});
好了,都搞完了,现在来用用看(还有些功能没有实现,比如ajax网络错误,应该有对应的处理,等等地方...我懒)
现在看看完整的代码:
/**
* jquery插件,用来扩展jquery分页插件,
* 该插件做以下事情:
* 1.$.ajax.post异步请求数据,数据格式{rows:[]};
* 2.将获取到的数据根据配置生成tbody内容
*/
(function($){
$.PageProcesser = function(tableId, url, pageSize, opts){
var that = this;
this.tableId = tableId;
this.url = url;
this.pageSize = pageSize ? pageSize : 10;
if(!tableId || !url){
throw "PageProcesser : the param tableId and url are required";
}
this.opts = jQuery.extend({
param:{},
rowHandler:function(index, data, tr){return true;},},
opts||{}
);
this.tdOpts = [];
$("#" + tableId + " th[name]").each(function(index, element){
var fieldName = $(this).attr("name");
var fieldOpts = $(this).attr("opts");
fieldOpts = fieldOpts ? eval("fieldOpts = " + fieldOpts) : {};
fieldOpts = jQuery.extend({handler:function(index, data, td){return true;}}, fieldOpts);
that.tdOpts.push({name:fieldName, index:index, opts:fieldOpts});
});
};
$.extend($.PageProcesser.prototype, {
callback:function(page_index, pagination){//pagination的回调函数
this.requester(page_index);
return false;
},
requester:function(page){//ajax请求数据
var requestParam = jQuery.extend({page:(page+1), rows:this.pageSize}, this.opts.param);
$.ajax({ type : "POST", url : this.url, data : requestParam, context:this,
success : function(json) {
this.handlerJson(json);
}
});
},
handlerJson:function(json){
var datas = json ? (json.rows ? json.rows : []) : [] ;
var tbody = $("#" + this.tableId + " tbody[data]");
tbody.html("");
for(var i=0 ; i<datas.length ; i++){
var tr = $("<tr></tr>");
for(var j=0 ; j<this.tdOpts.length ; j++){
var val = datas[i][this.tdOpts[j].name];
var td = $("<td></td>").text(val);
this.tdOpts[j].opts.handler(i, datas[i], td);
td.appendTo(tr);
}
this.opts.rowHandler(i, datas[i], tr);
tr.appendTo(tbody);
}
},
});
})(jQuery);
使用:
$(function() {
var pageHaper = new $.PageProcesser("table", "${path}/json", 10, {
param:{type:"1"},
rowHandler:function(index, data, tr){//双行变红
index % 2 == 0 ? tr.css("color", "red") : "";
}
});
$("#page_bar").pagination(100,{callback:function(pageIndex, pagination){
return pageHaper.callback(pageIndex, pagination);
}
});
});
<table id="table" style="border: 1px; width: 50%; text-align: center;">
<thead head>
<tr>
<th name="id">主键</th>
<th name="name">姓名</th>
<th name="link" opts="{handler:function(index, data, td){
var a = $('<a>');
a.attr('href','http://www.baidu.com/');
a.text('删除:' + data.id);
a.appendTo(td);
}}">操作</th>
</tr>
</thead>
<tbody data></tbody>
</table>
<div id="page_bar" style="margin-top: 50px;"></div>
效果:
后台代码(Spring mvc):
@ResponseBody
@RequestMapping(value = "/json")
public Object testJson(Integer page, Integer rows){
PageInfo<Map<String, String>> pageInfo = new PageInfo<Map<String,String>>(page, rows);
pageInfo.setRows(getMapList(pageInfo));
return pageInfo;
}
private List<Map<String, String>> getMapList(PageInfo<?> pageInfo){
List<Map<String, String>> rows = new ArrayList<Map<String,String>>();
for (int i = pageInfo.getBegin(); i < pageInfo.getEnd()*pageInfo.getPageNo(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("id", "id" + i);
map.put("name", "name" + i);
rows.add(map);
}
return rows;
}
PageInfo代码:
/**
* 分页 实体类 (封装分页请求和结果数据)
*/
public class PageInfo<T> implements Serializable {
private static final long serialVersionUID = 5367449251268716436L;
public static final int DEFAULT_PAGE_SIZE = 10;
/** 分页信息 */
private int pageSize = DEFAULT_PAGE_SIZE; // 每页记录条数
private int pageNo = 1; // 页码 从1开始
/** 查询参数 **/
private Map<String, Object> paramMap = new HashMap<String, Object>(); //查询条件
private Object paramObj; //查询对象
/** 结果数据 */
private Integer total; // 总记录数
private List<T> rows; // 当前页显示数据
private boolean plugin = false; //是否走分页插件
private String sqlId; //用于标识具体执行的分页标识
public PageInfo() {
super();
}
public PageInfo(Integer pageNo, Integer pageSize) {
this.pageNo = pageNo != null ? pageNo : 1;
this.pageSize = pageSize != null ? pageSize : PageInfo.DEFAULT_PAGE_SIZE;
}
public PageInfo(Integer pageNo, Integer pageSize, Object paramObj) {
this.pageNo = pageNo != null ? pageNo : 1;
this.pageSize = pageSize != null ? pageSize : PageInfo.DEFAULT_PAGE_SIZE;
this.paramObj = paramObj;//防止sql配置文件中空判断时报空指针
}
/**
* 获取分页begin参数 limit {begin}, {end}
*/
@JsonIgnore
public int getBegin() {
Integer begin = (pageNo - 1) * pageSize;
if (begin < 0) {
begin = 0;
}
return begin;
}
/**
* 获取分页end参数 limit {begin}, {end}
*/
@JsonIgnore
public int getEnd() {
if (pageSize <= 0) {
return DEFAULT_PAGE_SIZE;
} else {
return pageSize;
}
}
//get set 方法略 改JsonIgnore的都忽略吧,
}
需要注意的是:安全问题,后台数据显示到前台一定要过滤或者编码,否则容易有xss安全问题.
以上皆为原创,转载请注明!