[javascript学习指南]Javascript分页组件:xPagination.js使用例子

更新时间:2020-05-08    来源:js教程    手机版     字体:

【www.bbyears.com--js教程】

加入新公司后,一直忙得飞起。由于在新公司的工作包括写一些公用组件,比如日历啊,分页啊什么的,这个分页组件我觉得要用的人比较多,所以把它独立了出来,做成了一个无依赖的原生JS版本,供需要的人使用。

组件下载:https://github.com/wslx520/wslx520.github.io/tree/master/pagination

使用方法:
var xxx = xPagination(pagediv, options);
其中pagediv是一个div节点,options是参数

options参数说明:
支持设置的选项:
max : 最多同时显示好多页
curr : 当前页码
size : 每页显示多少条,默认15。可以是15,30,50的任一个,如果传为false,则不显示切换每页显示条数的标签
    2015.12.17: size可以传入任何数字,如果不传值或传为false,则默认是15; 且不再与是否显示条数切换功能有关
pages : 总好多页。可以不传而只传items,则会由items和size计算出pages
items : 总数据条数推荐。使用这个参数,可以在切换每页显示条数时,动态修正页码数量
onpagination : 函数,在页码跳转时触发,此函数执行时会自动传入两个参数:page(当前页), size(当前页显示条数)
info : 是否显示页码信息,默认true,会加入一个page-text用来显示“共N页,当前是第n页”这样的信息
    2015.12.17: 新增功能,info可以是一个函数,此函数会接收options做为参数,返回一个字符串,插入到info的div中,且每次翻页都会刷新。
jump : 是否允许输入页码跳页,默认true,会加入一个页码输入框和确定按钮
prev :上一页按钮显示的文字,设为false则不显示上一页按钮,下同
next :下一页按钮显示的文字,同上
last :末页按钮显示的文字,同上;默认false (2015/12/14 去掉此选项,因为页码算法的改变,页码在任何时候,都会显示第一页和最后一页的页码,用不着用按钮来跳了)
first :首页按钮显示的文字,同上;默认false 2015/12/14去除
showSize : 2015.12.17是否显示左侧的切换每页多少条,默认false。如果设为true,则会显示当前页码分别乘以1,2,3的size切换;如果设为一个数组如[20,40,80],则会以此数组生成对应的size切换

xPagination实例的属性:

options : 对象,上面列出的静态设置选项
currPageElement : 当前页码的node
pageList : Node数组,页码node的列表


本文只是说明一下写这个组件的一些思路,仅供参考。

更新记录:

2015/12/31: 修复一个大意之下的bug:点下一页按钮无效(会跳到第1页)

原由:以前用pages局部变量保存了总页数(如果不传则是0),但会在后面修复一次,但我把生成页码的函数独立出去后,相当然的删除了重设pages变量的代码,结果导致pages一直是0.

解决办法:直接调用options.pages,这个的值是会正确设置的。

—————–

这个组件起源比较仓促,我本来是去总部“学习”这个框架的组件开发方式的,当时写了一个简单的,后来才要我完善,再后来我就提取出来了一个纯JS版本,再后来我就要同时维护两个版本了,今天同时更新了两个版本,功能基本确定下来了,所以我决定发布此文。

分页组件大家见了很多,样式本文就不提了,我会说一些JS上的实现逻辑。

最初的版本,我打算让分页组件可以自定义最多显示多少页,是否显示上下页按钮,首页末页按钮;且在跳页码的时候要触发一个函数(供发起ajax请求之类的用)。

然后新增了需求:要显示省略页,比如最多同时显示8页,你却有100页,那么,8页后面的就要显示个省略号,让用户知道后头还有。

这个需求就引出了另一个需求:当我翻到靠后的页码时,那么前面也要显示省略号;当当前页十分靠近第一页或最后一页时,则要隐藏前面或后面的省略号。

当然,还有个必须要有的需求:当在第1页时,则上一页与首页按钮要禁用;在最后一页时,则下一页与末页按钮要禁用。

当时还出了个我印象比较深的问题,就是总数只有一页时,则上下页按钮,首末页按钮,全都要禁用。而当时我的判断逻辑用的是else if,也就是想当然的认为当前页等于1,就不会等于总页数——结果总页数就是1,结果出现只禁用了上一页按钮,但下一页按钮还可以点。

html结构:
那么html结构就会是这样:

首页-上一页-省略号-1,2,3,4-省略号-下一页-末页

这时候我又想到,如果当前最多显示8页,但实际上总页数只有5页,则用不着生成省略号了。那么就又多了个判断:如果有总页数超出最大同时显示页数,才生成省略号。

然后就是具体代码实现。而我在这里走了弯路。

首先会了节省代码提高效率,我用一个数组来lis保存所有页码的html字符串,最后join并插入到对应节点。

比如共100页,最多同时显示8页,那我翻到第9页时,就要把所有页码刷新一遍,从原来的1-8变成2-9,且前面的省略号就要显示出来了;当页码靠近最后一页时,则后面的省略号就要隐藏了。

为了控制两个省略号的显示与隐藏,我打算把他们缓存成变量,到时候直接hide(xxx)就行了。

但缓存这些元素的难点在于,我的上下页首末页按钮是可要可不要的,而我的页码全是用innerHTML生成的,所以没法直接在生成的时候得到对应的元素,而必须通过计算是否有上一页,首页,算出对应情况下的省略号的index,然后缓存下来。

在这里我出了好几个bug,都是比如没有首末页按钮时正常,有人加入了这两个按钮,而我的index没取对,就报错了。

最后我写了很长一串的三元运算来计算正确的省略号index。

而对于上下页按钮,首末页按钮的index,也需要这样搞。

所幸的是我们出了个分页组件的规范文档,里面没有提到过要首末页功能。

但是,页码生成的规范却改了,

新的规范是这样:
上一页-1-省略号,12,13,14-省略号-44-下一页

也就是:始终显示1与最后一页的页码,省略号出现在中间与首末页之间。所以,很显然不再需要显示“首末页”按钮了。

但之前的页码生成规则就要推翻了。

相同的是,我还是打算只在总页数超出最多显示页数时才生成省略号。

改成后面的规范之后,其实总的dom元素更少了。我在忙了半个月其他事后,重新理了一下生成页码的思路。

首先,页码最少有一页

所以我直接给lis数组push了一页。

然后,循环push 2,3,4。。。这样的页码,注意,这里的循环是从2开始了——当最大页就是1页时,此循环压根不会进入。

再然后,就是输出最后一页的页码——最后的页码数字始终不会变化。这里也需要判断一下:只有当最后一页大于1时,才有必要输入最后一页。

页码全部push进去以后,再判断是否有上一页的参数:prev,有就用unshift加入上一页;下一页则用push

最后,依然是join数组并附给对应的innerHTML。

然后就是之前就已经遇到过的难题了:怎么判断出上一页下一页及两个省略页的index?

一位同事提醒我,说我不应该写这么复杂的判断,直接循环所有页码,针对页码的情况做相应操作。之前我认为从性能上考虑,这样是不可取的,后来觉得这样对性能造不成多严重的拖累——因为,我改变中间部分的页码时,也是通过循环,就算加入上下页与省略页,也就是多了4个而已。

而通过前面产生innerHTML的过程我知道,页码中的上下页,省略页,是生成之后永远不会改变的,最多就是禁用,启用,隐藏与显示,其他数字页码,会改变里面的数字——比如从2-7变成3-8。

于是,我把每个页码都加了个ui-page属性——这本来是用来保存此页码的真实页数的,但我把上下页分别设为了prev与next,省略页则是ellipsis,当我循环页码队列时,如果是数字,就改变innerHTML(这里我先判断当前页是否真需要改变,否则不变);如果是这三个单词,则判断当前页与总页数的关系,进行隐藏与显示等操作。

这里用到了一个技巧:当两个函数A与B,需要的参数是一样的,而我要根据不同的条件,分别调用两个函数,该怎么做?

答案是:

1
(aaa ? A : B)(arg1, arg2);
比如在循环页码时,当 当前页是1时,我就要禁用prev,否则我就要启用prev,而禁用启用是通过addClass与removeClass来做的,二者需要的参数是一样的。

页码生成算法

分别有两种页码生成算法,相同的是,当前页要始终处于所以页码的中央位置(当然,太靠前或靠后就例外了)。一种是中间部分的数字页码全需要更新的时候,我写了个函数,用来计算出现在的页码该从哪个数开始:

 

// 根据当前页,总数页,最多显示页计算出应显示的页码
        pageCalc = function (curr, pages, max) {
            //console.log("curr,pages,max",curr,pages,max)
            var start = 1,
                // var end = max;
                //var truehalf = max / 2;
                half = Math.floor(max / 2),
                maxLength = Math.min(pages, max) - 1;
            // if (pages < end) {
            //     end  = pages;
            // }
            //console.log("start,half,max",start,half,max)
            //如果总页数已超过最多显示页,且当前页大于最多显示页的一半,当前页放中间
            if (pages > max && curr >= half) {
                start = curr - half;
                // end =  (curr + half) > pages ? pages : curr + half;
                if (curr === pages - 1) {
                    // start = curr - half -(half                     start = curr - (half + 1);
                }
                if (curr === pages) {
                    start = curr - maxLength;
                    start = start || 1;
                }
            }
            // 如果start + 最大显示页,已经超过了总页数,那么start需要前移
            if (start + maxLength > pages) {
                start = pages - maxLength;
            }
            start = start > 0 ? start : 1;
            return start;
        }
这个函数需要3个参数,依次是当前页,总页数,和最多同时显示的页数,执行后返回一个start,即该从哪一页开始。其中有很重要的一点,就是如果start+最大显示页,已经超过了总页数,那就应该把start往前移了,让start生成的页码正好在最后一页结束(同时,这个时候也应该隐藏末尾端的省略号了)。

我的分页组件中,有个max参数指定最多同时显示页,比如8页,7页,所以他存在奇偶数的问题,在计算页码的时候要特别注意。

改需求后的算法

改需求后,由于第1页与最后一页,始终数字都是不变的,所以刷新页码的时候直接就可以无视他们。这个算法就比较简单了,只涉及到逻辑问题:


// 默认假设页码居中
                    var start = page - (Math.ceil(half - 1) - 1);
                    if (page <= Math.ceil(half)) {
                        // 页码靠前
                        start = 2;
                    } else if (page >= Math.ceil(pages - half)) {
                        // 页码靠后
                        start = Math.floor(pages - half);
                    }
                    setPageNumbers(start);
里面的half是max/2(未四舍五入的),page是传入的要跳至的页码(也就是会变成curr)。我们以两个不同的实际场景来说明这几句算法:

1,max=8,pages=21

此时half是整数4。

1)当curr(当前页,我用[]包起来表示)为默认1时,html结构是这样的:

[1],2,3,4,5,6,7,…,21

2)此时,当curr>4时,比如5,html结构会变成:

1,…,3,4,[5],6,7,8,…,21

3)当curr靠后时,比如17:

1,…,15,16,[17],18,19,20,21

4)当curr<17时,比如16:

1,...,14,15,[16],17,18,19,...,21

此时实际上16的位置与2)下的5位置相同

2,max=7,pages=21

此时half是3.5。

1)默认curr=1时

[1],2,3,4,5,6,…,21

与上一种情况,少了一页

2)当curr=5

1,…,3,4,[5],6,7,…,21

3)当curr>17,比如18

1,…,16,17,[18],19,20,21

4)当curr=17

1,…,15,16,[17],18,19,…,21

妈呀累死我了,简单地说就是通过以上推断,得出了最终的计算公式

该省事儿的时候要省事儿
比如,pages<=max时,省略号就没有了,此时应该直接改变页码,将对应index的页码设为active,就行了,再也不用过循环。

重新算页码的情况
比如,我初始化时,size=15,items=300,则总页码是20页;用着用着我点了一下”30″,也就是每页变成30条了,则总页码应该变成10了。

更糟糕的是,如果你此时正在第20页,总页码变成10了,你该去哪儿?

所以我就必须重置页码,并选中与当前页码最接近的页码。

这只是一种思路,所以我才会把生成页码的函数独立出来。

本文来源:http://www.bbyears.com/wangyezhizuo/93409.html

热门标签

更多>>

本类排行