開發背景
最近接了一個小型電商網站,各大商品分類都需要用到分頁的技巧,雖說我只是個后臺汪,但是不想搞前端的后臺不是一個好開發。參考了網上的某個簡單的分頁插件,重新封裝了下,支持ajax請求,data參數傳遞,分頁請求回調,真的很好用呢~
最終目的
既然是開發插件,那么使用一定要簡單粗暴,類似easyui datagrid這樣:
$('#dg').datagrid({
url:'datagrid_data.json',
columns:[[
{field:'code',title:'Code',width:100},
{field:'name',title:'Name',width:100},
{field:'price',title:'Price',width:100,align:'right'}
]]
});
所以我大概構思了下,我的page插件應該是這樣的:
$(".test").page({
'url': '/data.json',
'maxShowItem': 7,
'data': {
'limit': 6,
'attr': 'attr'
},
'currentClass': 'currentPage',
'activeClass': 'active',
'disabledClass': 'disabled',
'callback': function(currentPage, pageCount, obj){
// 處理分頁內容
console.log(currentPage, pageCount, obj);
}
});
url是分頁查詢的請求地址,maxShowItem則是最多顯示多少分頁按鈕,data為每次ajax請求的參數,callback即是請求成功的回調,形參為當前頁碼currentPage,總頁數pageCount,和當前頁內容(總共結果數count,單頁數據集result)。
效果圖示
效果圖示
模仿著網易云音樂做的,然后有幾個關鍵點,我都用紅線標記出來了,大概說下各個標記和重要單位的意思:
- left/right,即左右分頁省略臨界點;
- unit,即是currentPage兩邊各分布著幾個分頁按鈕(不含首尾頁);
這就是一個分頁模型,當然實際開發中存在著許多條件因素,需要逐步來看。
即刻動手
這里推薦個jQuery插件編寫教程的地址:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html
首先定義Page插件的構造函數:
// 定義Page的構造函數
var Page = function(ele, opt){
this.$ele = ele;
var defaults = {
// 分頁ajax地址
'url': '',
// 最多展示分頁按鈕數
'maxShowItem': 7,
// ajax請求默認參數
'data': {
'start': 0,
'limit': 10
},
// 當前頁碼class名稱
'currentClass': '',
// 激活的頁碼class名稱
'activeClass': '',
// 失效的頁碼class名稱
'disabledClass': '',
// 省略class名稱
'ellipsis': '',
// 請求回調,當前頁碼,總頁碼數,當前頁碼內容(當頁結果result,數據總數count)
'callback': null
};
this.opt = $.extend({}, defaults, opt);
};
然后拓展Page的方法:
// 定義Page的方法
Page.prototype = {
'ajax': function(currentPage){
var data = this.opt.data;
var page = this;
data.start = (currentPage - 1) * data.limit;
$.ajax({
'url': this.opt.url,
'type': 'get',
'dataType': 'json',
'data': data,
'success': function(obj){
var pageCount = Math.ceil(obj.count / data.limit);
page.resetPageItem(currentPage, pageCount);
page.opt.callback(currentPage, pageCount, obj);
},
'error': function(XMLHttpRequest, textStatus, errorThrown){
console.log(XMLHttpRequest);
console.log(textStatus);
console.log(errorThrown);
}
});
},
// 重置分頁item(第一次,和每次item點擊都會觸發)
'resetPageItem': function(currentPage, pageCount) {
var page = this;
var pageItem = this.getPageItem(currentPage, pageCount);
this.$ele.html(pageItem);
// 為每個item綁定點擊事件
this.$ele.children('a[class=\'' + this.opt.activeClass + '\']').on('click',function(){
var $this = $(this);
var currentPage = parseInt($this.attr('page-data'));
page.ajax(currentPage);
});
},
// 根據總頁數和當前頁數,得到分頁item的html內容
'getPageItem': function(currentPage, pageCount){
var prePage = currentPage - 1;
var nextPage = currentPage + 1;
var prePageClass = this.opt.activeClass;
var nextPageClass = this.opt.activeClass;
if (prePage <= 0) {
prePageClass = this.opt.disabledClass;
}
if (nextPage > pageCount) {
nextPageClass = this.opt.disabledClass;
}
var appendStr = '';
// appendStr += '<a href=\'#\' class=\'' + prePageClass + '\' page-data=\'1\'' + '>首頁</a>';
appendStr += '<a href=\'#\' class=\'' + prePageClass + '\' page-data=\''+ prePage +'\'>< 上一頁</a>';
var unit = (this.opt.maxShowItem - 3) / 2;
// 左邊臨界
var left = currentPage - unit;
// 右邊臨界
var right = currentPage + unit;
if(left <= 1){
right = this.opt.maxShowItem - 1;
}
if(right >= pageCount){
left = pageCount - (this.opt.maxShowItem - 2);
}
var leftEllipsis = false;
var rightEllipsis = false;
for (var i = 1; i <= pageCount; i++) {
var itemPageClass = this.opt.activeClass;
// 左側省略號
if(i > 1 && i < left){
if(!leftEllipsis){
itemPageClass = this.opt.ellipsis;
appendStr+='<span class=\'' + itemPageClass + '\'>...</span>';
leftEllipsis = true;
}
continue;
}
// 右側省略號
if(i < pageCount && i > right){
if(!rightEllipsis){
itemPageClass = this.opt.ellipsis;
appendStr+='<span class=\'' + itemPageClass + '\'>...</span>';
rightEllipsis = true;
}
continue;
}
if(i == currentPage){
itemPageClass = this.opt.currentClass;
}
appendStr+='<a href=\'#\' class=\'' + itemPageClass + '\' page-data=\'' + i + '\'>' + i + '</a>';
}
appendStr += '<a href=\'#\' class=\'' + nextPageClass + '\' page-data=\'' + nextPage + '\'>下一頁 ></a>';
// appendStr += '<a href=\'#\' class=\'' + nextPageClass + '\' page-data=\'' + pageCount + '\'>尾頁</a>';
return appendStr;
}
};
這里要講述下,我拓展了Page的三個方法,分別是
- ajax:點擊一個active的分頁按鈕發起一個ajax請求,請求成功回調中初始化分頁按鈕items,同時調用Page構造方法參數中的callback;
- resetPageItem:通過當前頁currentPage和總頁數pageCount,獲取分頁按鈕items的html內容,重置分頁按鈕items,同時對active的item綁定好click的ajax事件;
- getPageItem:獲取分頁按鈕items的html內容,其實這個也可以寫到resetPageItem中,只不過個人覺得生成html的邏輯有點復雜,可以和items的click綁定分開;
最后就是拓展jQuery的方法,使用Page對象:
// 在插件中使用Page對象
$.fn.page = function(opt){
var page = new Page(this, opt);
// 初次加載
page.ajax(1);
};
加上命名空間,防止變量污染:
;(function(){
// 插件代碼
})(jQuery);
這樣我們就編寫完了整個分頁控件,即可像最終目的中的那樣,使用一個div的簡單配置就能夠一鍵實現ajax的分頁功能,第一次自己編寫呢,成就感爆棚啊~~