Vue3实现Pagination分页组件(一)基础实现

5,579 阅读4分钟

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

写在前面

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

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

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

组件Props

分页组件的渲染,需要知道数据量的大小total,和需要被切割的每页显示条数pageSize,从而确定总页数。还有当前页pageNum,如果可以,你可以使用 v-model 属性绑定这个值。如果需要支持显示条数的切换,还需要传入sizeList以配置可选的条数。

如上,实现最简单的分页组件,需要包含 props 属性:

const props = defineProps({
    total: { type: [Number, String], default: 0 }, // 总数 The total number of
    pageNum: { type: [Number, String], default: 1 }, // 当前页数 The current number of pages
    pageSize: { type: [Number, String], default: () => 10 }, // 每页显示条数 Size of entries per page

    // 可选
    sizesList: { type: Array, default: () => [10, 20, 50, 100] }, // 每页显示条数的选项设置 Option setting to display number of entries per page
});

组件 Emits

分页组件需要通过事件触发,通知父组件跳转至指定的页码page-change,简单的处理逻辑包括上一页、下一页和指定页码。如果含有可选切换的每页显示条数,则需要size-change事件触发。

const emit = defineEmits(["page-change", "size-change"]);

核心实现

以上完成了一个简单分页组件的最简化属性和 event 设计,接下来是一些组件内核心方法的实现。

使用ref 定义一些响应式变量,以供组件使用;这里需要说明下,像total属性,支持传入的时候使用String 或 Number 类型,这样的好处是在使用过程中,可以忽略 v-bind,即total="100":total="100"写法都可以。因此在处理这些属性过程中,要注意转换下数据类型为 Number。

/** 当前激活的页码 */
const currentPage = ref(Number(props.pageNum));

/** 每页显示的条数 */
const currentPageSize = ref(Number(props.pageSize));

/** 总页数 */
const totalPagesNum = ref(0);

设置当前激活的页码

在进行「上一页」「下一页」或指定页码操作时,需要设置当前激活的页码,以及判断当前页是否为首页或尾页,用于上下翻页按钮的禁用状态控制,同时触发事件给父组件重新加载数据。

/**
* 设置当前激活的页码
* @param {Stirng} type 'prev'-上页, 'next'-下页, 'page'-指定页码
* @param {Number} pageNum
*/

const setCurrentPage = (type, pageNum = 1) => {
    let num = currentPage.value;
    type === "prev" ? num-- : type === "next" ? num++ : (num = Number(pageNum));

    // 限制页码的边界值,最小为 1,最大不超过总页数
    currentPage.value = num < 1 ? 1 : num > totalPagesNum.value ? totalPagesNum.value : num;
    emit("page-change", currentPage.value);
};

设置每页显示条数

通常分页器都应支持每页显示条数的切换,因此在切换后,需要触发事件给父组件重新加载数据。

/**
* 设置每页显示的条数
* @param {Number} v
*/
const setCurrentPageSize = (v) => {
    currentPageSize.value = Number(v);
    emit("size-change", currentPageSize.value);
};

初始化组件

在初始化组件时,需要计算总页数以及调用setCurrentPage,判断传入的pageNum是否超过边界值。

watchEffect(() => {
    // 根据传入的 total 计算总页数
    totalPagesNum.value = Math.ceil(props.total / currentPageSize.value);

    // 相应的,在每页条数和总页数有变化时,需要重新设定当前激活页,以防止溢出边界值的情况
    setCurrentPage("page", currentPage.value);
});

欢迎阅读其它文章