jQuery分页插件

开发背景

最近接了一个小型电商网站,各大商品分类都需要用到分页的技巧,虽说我只是个后台汪,但是不想搞前端的后台不是一个好开发。参考了网上的某个简单的分页插件,重新封装了下,支持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)。

效果图示

效果图示

模仿着网易云音乐做的,然后有几个关键点,我都用红线标记出来了,大概说下各个标记和重要单位的意思:

  1. left/right,即左右分页省略临界点;
  2. 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的三个方法,分别是

  1. ajax:点击一个active的分页按钮发起一个ajax请求,请求成功回调中初始化分页按钮items,同时调用Page构造方法参数中的callback;
  2. resetPageItem:通过当前页currentPage和总页数pageCount,获取分页按钮items的html内容,重置分页按钮items,同时对active的item绑定好click的ajax事件;
  3. 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的分页功能,第一次自己编写呢,成就感爆棚啊~~

开源地址

https://github.com/caojiantao/page

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容