Bootstrap

前端分页组件实现逻辑

前言

前段时间图懒,数据展示的分页,自己随便的实现了一下,具体咋实现的就不说了(手动捂脸)。反正导致的问题就是每页加载数据很多,页面响应慢。老大让优化一下,于是就从头捋一遍分页逻辑。觉得很容易?动手试试?好吧,确实容易。但是,如果从头走一遍,还是需要一点时间的。参考了前端的分页组件实现,整理了本文

要实现什么样的效果?

根据我们要实现的效果,才能分析如何去实现。从上图可以看出来,该分页组件由以下几个部分组成:

上一页、下一页、首页、尾页、省略号(2个)、当前页、当前页的两边分别有2个(共4个)。所以,该分页组件由11个部分组成,我们用totalPart这个变量来表示

详细分析

主要的实现难点在于何时该出现省略号。分析出来何时该出现省略号,需要以下几个变量来帮助理解:

分页总数:totalPage

当前页:currentPage

当前页的两边页码数量:arroundPage

下边我们逐一分析以下几种情况:

  • 没有省略号

  • 仅当前页之后出现省略号

  • 仅当前页之前出现省略号

  • 当前页的前后均出现省略号

没有省略号

从上边的分页效果图可以看出来,上一页和下一页这两个部分是固定不变的,那么中间就由9(totalPart-2)个部分组成。所以,当totalPage <= 9时,位置够用,不需要省略号

仅当前页之后出现省略号

首先,我们使用省略号的意义其实就是为了省位置,如果省略号仅代表一个部分,那省略号就没意义了,如:1,...,3,4,5,这里的省略号代表的就是2,还不如直接用2呢,都是占一个位置。所以,使用省略号,起码要代表两个位置

那清楚了这个,现在就分析一下,什么情况下,仅当前页的后边出现省略号(出现省略号的前提条件是totalPage > totalPart -2,否则,位置是完全够用的,就不需要省略号)

要分析仅当前页的后边出现省略号,那就需要找出,当前页的前边恰好不出现省略号的情况。根据前边我们的分析,省略号至少要代表两个位置,因此我们就取最小值2。这个时候是前边恰好不出现省略号,当省略号所代表的位置越多,则currentPage就越大,也就是越靠后

现在就是找出currentPage的临界值,currentPage临界值 = 首页 + 省略号最小值(2) + currentPage左边的值arroundPage(2) + 1,后边的加一就是指arroundPage后边的那个位置。把当前页之前恰好不出现省略号的位置用beforePosition表示。所以,当currentPage < beforePosition时,当前页之前不会出现省略号。因此,beforePosition = 1+2+2+1

仅当前页之前出现省略号

与上边的仅当前页之后出现省略号的逻辑一样。后边恰好不出现省略号的临界位置为:totalPage(尾页) - 省略号最小值(2) - arroundPage右边的部分(2) - 1,减一表示的是arroundPage前边的那个位置。把把当前页之后恰好不出现省略号的位置用afterPosition表示。所以,当currentPage > afterPosition时,当前页之后不会出现省略号。因此,

afterPosition = totalPage-1-2-2-1

当前页的前后均出现省略号

这种情况是最简单的情况,去掉上边的两种情况,就是这种情况。也就是当currentPage >= beforePosition && currentPage <= afterPosition时,当前位置之前和之后均会出现省略号

分页组件的每种情况展示

上边分析了省略号可能出现的每种情况,分页组件的每个地方展示就很简单了

从上边可知,我们这里的分页组件一共有11个位置(totalPart),因为上一页和下一页一直都会存在,所以我们实际关心的只有11-2=9个位置

当省略号只出现在当前页之后时,最后两个位置一定是省略号和totalPage。因此,省略号之前还剩9-2=7个位置,这七个位置用变量oneEllipsis表示,剩余页码从1展示到oneEllipsis即可。

同理,当省略号只出现在当前页之前时,前边的两个位置一定是省略号和1,所以后边的页码就是从totalPage-oneEllipsis到totalPage

当两边都出现省略号时,前边两个位置和后边两个位置一定分别是1和省略号、省略号和totalPage。中间的自然就是currentPage和左右两边相邻的arroundPage个页码

下边是使用PHP实现的,仅供参考:

class Page {
const AROUND = 2;
const SHOW_PAGE_COUNT = self::AROUND*2+7;//1+2+2+2 = 7
/**
 * 获取分页信息
 * @params $currentPage integer
 * @params $totalPage integer
*/
    public function getPageInfo($currentPage, $totalPage) {
        $pageInfo = [];
        //只出现一个省略号,剩余展示页码的个数
        $oneEllipsis =      self::SHOW_PAGE_COUNT-4;
        //仅前边出现省略号的临界位置
        $beforePosition = 1+2+self::AROUND+1;
        //仅后边出现省略号的临界位置
        $afterPosition = $totalPage-2-self::AROUND-1;

        //不出现省略号的情况
        if ($totalPage <= self::SHOW_PAGE_COUNT-2) {
            $pageInfo = range(1, $totalPage);
        } else {
            //只有后边出现省略号
            if ($currentPage < $beforePosition) {
                $arrPage = range(1, $oneEllipsis);
                $endPageInfo = ['...', $totalPage];
                $pageInfo = array_merge($arrPage, $endPageInfo);

            } else if ($currentPage > $afterPosition) {//只有前边出现省略号
                $startPageInfo = [1, '...'];
                $arrPage = range($totalPage-$oneEllipsis+1, $totalPage);
                $pageInfo = array_merge($startPageInfo, $arrPage);
            } else {//两边均出现省略号
                $startPageInfo = [1, '...'];
                $arrPage = range($currentPage-self::AROUND, $currentPage+self::AROUND);
                $endPageInfo = ['...', $totalPage];
                $pageInfo = array_merge($startPageInfo, $arrPage, $endPageInfo);
            }
        }

        return $pageInfo;
    }
}