Vue3实现Pagination分页组件(四)限制最大页码数

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

写在前面

在 B 端的 web 开发中,分页组件或者叫分页器,是较为常用的控件之一,通常配合表格或列表,实现数据量大的情况下,分页拆解数据的功能。

由于完整实现的篇幅较大,所以我分成了以下几部分逐个讲解,这里是第四讲:限制最大页码数,如果你需要查看完整的源代码实现,请访问Pagination 分页组件

  • 基础实现
  • 分页操作控件
  • 自定义控件布局
  • 限制最大页码数

需求拆分

假设某些情况下数据量较多,被拆分的页数也特别多,页码占据了屏幕宽度的绝大部分,甚至是超出了页宽,这样不仅不美观,用户体验也是极差的。在这种情况下,除了只显示上下翻页之外,就需要限制其最大的可展示页码数量,超出限制之外的,将其折叠,效果图类似于:

截屏2022-04-04 06.12.12.png

截屏2022-04-04 06.13.00.png

截屏2022-04-04 06.13.25.png

如效果图所示,在页码大于 20 页时,折叠一部分首尾的页码,这里是以限制最大数量为 7 的例子,我们来看看具体是实现思路

传入 pagerCount

定义一个pagerCount属性,限制其最大的显示页数,其余折叠,注意,由于计算便利,这里的值必须为大于等于 5 且小于等于 21 的奇数。

const props = defineProps({
    pagerCount: { type: [Number, String], default: 7, validator: pagerCountValidator }, // 最大页码数,须为大于等于 5 且小于等于 21 的奇数
});

const pagerCountValidator = (v) => {
    const num = Number(v);
    if (isEvnetNum(num) || num < 5 || num > 21) {
        console.warn("属性 `pager-count` 须为大于等于 5 且小于等于 21 的奇数");
        return false;
    }
    return true;
};

export const isEvnetNum = (num) => Number(num) % 2 === 0;
复制代码

改造 Pager 控件

有上面分析可以看到,渲染的页码有两种,一种是数字跳转,一种是渲染成折叠的省略号,这里用numberellipsis区分。 当页数小于限制最大数量时,无需特殊处理,直接生成页码列表即可。

const { pages, currentPage, pagerCount } = props;
pageList.value = [];

if (pages < pagerCount + 1) {
    for (let i = 1; i < pages + 1; i++) {
        pageList.value.push({ index: i, type: "number" });
    }
}
return;
复制代码

当总页数超过限定的最大页数时,需要单独处理分页显示逻辑。

定义指定触发折叠的数值omit_num,规则为最大页码数的一半+1,四舍五入取整数,示例:限制最多 7 页,则该数值为 (7 / 2 + 1) = 4.5 -> 5

const omit_num = Number((pagerCount / 2 + 1).toFixed());
复制代码

定义除去首尾的两个页码后,中间需要动态变化的页码数量middle_page_count

const middle_page_count = pagerCount - 2;
复制代码

定义是否折叠之前的页码is_front_omit,规则为当前激活页等于或超过指定触发的数值时候

const is_front_omit = currentPage >= omit_num;
复制代码

定义是否折叠之后的页码is_end_omit,规则为当前激活页还没到指定触发的后面那几页的时候

const is_end_omit = currentPage <= Number(pages - omit_num);
复制代码

开始按顺序构建页码列表:

pageList.value = [{ index: 1, type: "number" }];
is_front_omit && pageList.value.push({ index: currentPage - middle_page_count, type: "ellipsis" });

// 动态变化的页码,根据折叠状态从而确定开始的页码
let start_index;
!is_front_omit && (start_index = 2);

is_front_omit && is_end_omit && (start_index = currentPage - Number((middle_page_count / 2).toFixed()) + 1);

!is_end_omit && (start_index = pages - middle_page_count);

for (let i = start_index; i < middle_page_count + start_index; i++) {
    pageList.value.push({ index: i, type: "number" });
}

is_end_omit && pageList.value.push({ index: currentPage + middle_page_count, type: "ellipsis" });

pageList.value.push({ index: pages, type: "number" });
复制代码

欢迎阅读其它文章

猜你喜欢

转载自juejin.im/post/7082500602810335240