十五分钟--分页逻辑--包学包会

13,189 阅读3分钟

分页组件的构成

废话不多说,我们先来分析一下一个分页组件的结构,实际这个分析很关键,比真正的逻辑判断重要的多,下面先看图:

我们可以看到此分页组件:

 《上一页》《下一页》 2 个 : 2
 《首页》《尾页》 2 个 : 2
 省略号 2 个 : 2
 当前页 1 个 : 1
 当前页左右各2个 :2 * 2

所以这个分页组件一共是由 2 + 2 + 2 + 1 + 2 * 2 = 11 个 元素构成。记住这个数,给这个变量起名字叫baseCount,待会要着重用它。分析到这逻辑实际已经完成74%了,是不是惊呆了?但是不要着急,我们继续分析一下分页组件需要哪些参数:

参数我已经标注好了,大家应该能知道这几个参数的意思,我就不解释了。好,说回刚才的那个baseCount,我们看看baseCount和组件变量有啥关系,发现只跟around有关系:baseCount = 2 + 2 + 2 + 1 + 2 * around。到这完成75%。

怎么使用baseCount

我们已经得到一个很简单的值:baseCount,但是它有什么用呢?实际上它很关键,我们能够用这个值来判断分页组件什么时候出现省略号。比如上面图中这个组件,除掉两边的上一页、下一页两个按钮,中间部分一共有11 - 2 = 9个元素,也就是说当分页的总数total <= 9的时候,是不需要省略号的,因为位置够用,都能显示完全。 进度达到了80%,go on,那什么时候出现省略号呢?嗯,这是个好问题,不过我们在确定啥时候出现省略号之前最好先弄清楚省略号有啥作用,这是本篇文章第二个关键点,也是最重要的一个关键点。

省略号的作用

先来看个小问题:1,...,3,4,5。这其中的省略号代表着啥?代表2吧。可是省略号这里直接用2不就行了吗,本身2也就占一个位置,用省略号岂不是多此一举(实际很多分页组件实现过程中省略号最少只代替了一个元素,也并没有大碍)。所以省略号的正确用法应该如这样:1,...,4,5,6(省略号代表2,3)或者6,7,8,...,12(省略号代表9,10,11)。因此个人认为省略号的作用就是最少代替2个元素

接下来看分页组件省略号出现的位置,一般会有三种情况,最开始的例子是一种,就是两边都出现省略号,还有两种如下:

1、只出现在后面 2、只出现在前面

出现省略号的前提条件是total > baseCount -2,因为此时可用位置不够显示完全所有页数,需要用省略号来代替。

a.先确定只出现在后面的情况(前面即将出现省略号),首先确定什么时候前面刚好出现省略号?根据刚刚得出的省略号的作用,也就是说它最少代替两个元素。所以我们就取这个最小值2,此时是在前面刚刚出现省略号,省略号代表的越多则说明cur越往后。

这个时候cur前面存在的元素以及个数为:首页(1) + 省略号最小值(2) + cur左边(around),所以cur所在位置为 = 1 + 2 + around + 1,标记一下叫startPosition。因此当cur < startPosition时前面是不会出现省略号的,仅在后面出现省略号。

b.同样的逻辑,我们还可以得出只在前面出现,后面不会出现省略号的一个临界位置:endPosition = 尾页(total) - 省略号最小值(2) - cur 右边的值(around) - 1。当cur > endPosition时只在前面出现省略号。

ok,逻辑分析已经完成了95%,还剩下一种两边都出现省略号的情况,我们不用分析了,除去刚才的两种情况就是它了,也就是当 startPosition <= cur && cur <= endPosition

其他的位置怎么显示

分析完省略号的位置,其他的就超级简单了,还记得刚才那个很重要的baseCount吗,还是用它。 刚才得到的baseCount是11,因为上一页和下一页一直都会存在。我们可以先不用管这俩,只看中间实际用到的9个位置。

我们可以看到当省略号只出现在后面时,可用位置的最后两个一定是 ... 和 total。所以这个省略号前面的还剩下9 - 2 = 7个位置,给这个变量也取个名字叫surplus,就从1开始显示到surplus就好了。也是同样的道理,当省略号只出现在前面时,前面的两个位置一定是 1 和 ...。所以后面各个位置就是从 (total-surplus) 一直到 total 了。

还有就是两边都出现省略号,前面两个肯定是 1 和 ...,后面两个又肯定是 ... 和 total。那么中间的就是cur以及其左右两边的相邻的around个。

当有省略号出现时,这种逻辑保证了分页组件总共需要的元素的个数是固定的,且只跟around有关,around取值建议为2或者3。到此,分页逻辑分析就全部结束了,下面是一个生成分页组件对应数组的方法,供各位小伙伴参考:

/**
 * 
 * @param {Number} total 
 * @param {Number} cur 
 * @param {Numbre} around 
 */
const makePage = (total,cur,around) => {
    let result = [];
    let baseCount = around * 2 + 1 + 2 + 2 + 2; //总共元素个数
    let surplus = baseCount - 4; //只出现一个省略号 剩余元素个数
    let startPosition = 1 + 2 + around + 1;//前面出现省略号的临界点
    let endPosition = total - 2 - around - 1;//后面出现省略号的临界点

    if(total <= baseCount - 2){ //全部显示 不出现省略号
        result =  Array.from({length: total}, (v, i) => i + 1);
    }else{ //需要出现省略号
        if(cur < startPosition){ //1.只有后面出现省略号
            result = [...Array.from({length: surplus}, (v, i) => i + 1),"...",total]
        }else if(cur > endPosition) { //2.只有前边出现省略号
            result = [1,'...',...Array.from({length: surplus}, (v, i) => total - surplus + i + 1)]
        }else{ //3.两边都有省略号
            result = [1,'...',...Array.from({length: around * 2 + 1}, (v, i) => cur - around + i),'...',total]
        }
    }

    return result
}
makePage(8,2,2);//[1, 2, 3, 4, 5, 6, 7, 8]
makePage(20,3,2);//[1, 2, 3, 4, 5, 6, 7, "...", 20]
makePage(20,10,2);//[1, "...", 8, 9, 10, 11, 12, "...", 20]
makePage(20,19,2);//[1, "...", 14, 15, 16, 17, 18, 19, 20]

总结

可以根据这个方法生成的数组来确定分页组件显示哪些内容,用react、vue或者源生js都可以,逻辑都是一样的,还可以根据需求加上跳转到第几页、是否显示首页尾页等相关功能和逻辑。