资讯动态

Vant Pagination 分页组件完全指南:从基础用法到源码级原理剖析

发布时间:2026/9/13 16:23:12 来源:尧图企业网站定制
Vant Pagination 分页组件完全指南从基础用法到源码级原理剖析【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant分页Pagination是移动端列表数据量过大时的标准解决方案通过将数据按页拆分、每次只渲染一页从而显著降低首屏渲染压力与网络传输成本。本文以 Vant 4 的 Pagination 组件为对象完整覆盖组件注册、四种核心用法基础分页、简单模式、省略号快速跳转、自定义按钮、全部 Props/Events/Slots 配置项、类型定义与主题定制方案并结合 Pagination.tsx 源码与 index.spec.ts 测试用例深入剖析页码计算、边界收敛与事件派发的底层实现帮助你在实际业务中熟练配置、深度定制并快速定位问题。组件引入与注册Pagination 与其他 Vant 组件一样支持按需引入与全局注册。在入口文件中通过app.use注册组件后即可在模板中使用van-pagination标签import { createApp } from vue; import { Pagination } from vant; const app createApp(); app.use(Pagination);从源码看index.ts 使用withInstall包装了组件并同时导出了paginationProps供自定义二次封装时复用 Props 定义、PaginationMode、PaginationProps与PaginationThemeVars类型此外还通过declare module vue为VanPagination注册了全局组件类型配合 IDE 可自动获得模板内的类型提示。若你的工程启用了按需引入如 unplugin-vue-components则无需手动注册插件会自动完成导入。核心用法演示基础用法通过 v-model 绑定当前页码数据总量与每页条数确定后组件会自动计算总页数。通过v-model绑定当前页码即可van-pagination v-modelcurrentPage :total-items24 :items-per-page5 /import { ref } from vue; export default { setup() { const currentPage ref(1); return { currentPage }; }, };示例中total-items为 24、items-per-page为 5组件会算出总页数为Math.ceil(24 / 5) 5首屏渲染出 5 个页码按钮并默认展示上一页 / 下一页按钮默认文案见下文 Props 说明。简单模式只展示页码描述将mode设置为simple可切换到简单模式。此时不再渲染具体的页码按钮而是以当前页/总页数的描述形式展示适合页面空间紧凑的场景van-pagination v-modelcurrentPage :page-count12 modesimple /在简单模式下页面结构为上一页按钮 页码描述 下一页按钮。从 Pagination.tsx 的renderDesc实现看页码描述默认渲染为${props.modelValue}/${count.value}的形式组件还预留了pageDesc插槽slots.pageDesc可在描述文案不能满足需求时自定义展示内容例如显示共 12 页或带图标的信息。简单模式下上一页/下一页按钮会带有边框样式bem(item, { border: mode simple })与多页模式下的无边框外观相区分。显示省略号快速跨页跳转当页数很多、无法一次展示全部页码时可设置show-page-size限制同时显示的页码个数并通过force-ellipses开启省略号按钮。点击省略号可一次向前/向后跳转一整组页码van-pagination v-modelcurrentPage :total-items125 :show-page-size3 force-ellipses /示例中总记录数 125、每页默认 10 条共 13 页show-page-size3使可见页码窗口为 3 个首屏与末屏页码不足 3 个时组件会自动在窗口两端补出省略号按钮。省略号按钮同样遵循点击跳转一整个窗口的交互逻辑详见下文源码原理。自定义按钮插槽全面定制通过prev-text、next-text插槽可替换上/下一页按钮内容通过page插槽可定制每一个页码按钮插槽参数包含页码信息常用于搭配图标实现更轻量的视觉风格van-pagination v-modelcurrentPage :total-items50 :show-page-size5 template #prev-text van-icon namearrow-left / /template template #next-text van-icon namearrow / /template template #page{ text }{{ text }}/template /van-pagination以上用法均可在 demo/index.vue 中查看完整可运行的示例该 demo 同时是 demo.spec.ts 快照测试的数据源。API 详解Props 配置项参数说明类型默认值v-model当前页码number-mode显示模式可选值为simplestringmultiprev-text上一页按钮文字string上一页next-text下一页按钮文字string下一页page-count总页数number | string根据页数计算total-items总记录数number | string0items-per-page每页记录数number | string10show-page-size显示的页码个数number | string5force-ellipses是否显示省略号booleanfalseshow-prev-button是否展示上一页按钮booleantrueshow-next-button是否展示下一页按钮booleantrue对应源码中的 Props 定义见 Pagination.tsxexport const paginationProps { mode: makeStringPropPaginationMode(multi), prevText: String, nextText: String, pageCount: makeNumericProp(0), modelValue: makeNumberProp(0), totalItems: makeNumericProp(0), showPageSize: makeNumericProp(5), itemsPerPage: makeNumericProp(10), forceEllipses: Boolean, showPrevButton: truthProp, showNextButton: truthProp, };几个关键点需要特别注意page-count的优先级高于total-items / items-per-page源码中总页数的计算逻辑为const count pageCount || Math.ceil(totalItems / itemsPerPage)即显式传入page-count时优先使用它否则才根据总记录数与每页条数推算。total-items为 0 时计算出的总页数为 0但组件通过Math.max(1, count)将总页数强制收敛为至少 1 页避免出现空分页器。prev-text/next-text的默认文案与国际化联动当未传文字时组件回退到props.prevText || t(prev)。t来自createNamespace(pagination)会从当前语言包的pagination.prev/pagination.next字段取值——例如 en-US.ts 中为 Previous/Next中文为上一页/下一页。通过 Locale 组件 切换语言后按钮文案会自动跟随无需额外处理。show-prev-button/show-next-button默认开启truthProp置为false可隐藏对应按钮结合 index.spec.ts 的测试可知隐藏后对应的.van-pagination__item--prev/.van-pagination__item--nextDOM 节点不会渲染。该特性在第一页/最后一页不需要翻页入口或仅展示页码等定制场景中很有用。所有数值型参数page-count、total-items、items-per-page、show-page-size均为number | string传入字符串如5会被内部通过运算符正确转换为数值。Events 事件事件名说明回调参数change页码改变时触发-源码中组件声明了emits: [change, update:modelValue]。需要区分两个事件点击页码/翻页按钮时组件先emit(update:modelValue, value)同步 v-model再emit(change, value)通知业务侧而change事件仅在页码真实发生变化时触发——updateModelValue内部先对目标页码做clamp(value, 1, count.value)边界收敛并在props.modelValue ! value时才派发事件因此点击当前页或边界外的页码不会产生多余的事件回调。测试 index.spec.ts 验证了点击第 3 页、上一页、下一页依次触发change且回调值分别为3、2、3。Slots 插槽名称描述参数page自定义页码{ number: number, text: string, active: boolean }prev-text自定义上一页按钮文字-next-text自定义下一页按钮文字-page插槽接收三个参数number为页码数字text为展示文本省略号场景下为...active标识当前页是否处于激活态可在自定义内容中据此做高亮处理。测试 index.spec.ts 演示了page插槽的用法({ text }) foo ${text}。此外上文提到源码中还预留了未在文档表格中列出的pageDesc插槽用于简单模式下自定义页码描述内容属额外能力按需使用即可。类型定义组件在包入口导出了以下 TypeScript 类型便于在组合式 API 或二次封装中声明类型import type { PaginationMode, PaginationProps } from vant;PaginationMode为simple | multi联合类型PaginationProps由paginationProps通过ExtractPropTypes推导而来见 Pagination.tsx与组件 Props 完全同步避免了手写类型与实现不一致的问题。主题定制CSS 变量组件通过 CSS 变量暴露了完整的定制入口默认值定义在 index.less类型声明见 types.ts名称默认值描述--van-pagination-height40px分页条高度--van-pagination-font-sizevar(--van-font-size-md)字体大小--van-pagination-item-width36px页码项最小宽度--van-pagination-item-default-colorvar(--van-primary-color)页码项文字/激活背景色--van-pagination-item-disabled-colorvar(--van-gray-7)禁用态文字颜色--van-pagination-item-disabled-backgroundvar(--van-background)禁用态背景色--van-pagination-backgroundvar(--van-background-2)分页条背景色--van-pagination-desc-colorvar(--van-gray-7)页码描述文字颜色--van-pagination-disabled-opacityvar(--van-disabled-opacity)禁用态不透明度使用方式有两种在全局样式中覆盖变量或通过 ConfigProvider 组件 按局部作用域动态设置主题。例如把激活页码改成品牌色并压缩高度van-config-provider :theme-vars{ paginationHeight: 36px, paginationItemDefaultColor: #ff6b00 } van-pagination v-modelcurrentPage :total-items24 :items-per-page5 / /van-config-provider从样式源码看激活页码--active与按压态:active都会将文字变白、背景变为--van-pagination-item-default-color禁用态则同时应用--van-pagination-item-disabled-color、--van-pagination-item-disabled-background与--van-pagination-disabled-opacity因此自定义这三个变量即可完整控制上/下一页按钮在首末页的置灰效果。源码级原理剖析总页数的计算与收敛总页数count是组件一切渲染的前提其计算逻辑Pagination.tsx为const count computed(() { const { pageCount, totalItems, itemsPerPage } props; const count pageCount || Math.ceil(totalItems / itemsPerPage); return Math.max(1, count); });即page-count显式传入时直接采用否则按total-items / items-per-page向上取整。最终经过Math.max(1, ...)收敛保证至少 1 页。可见页码窗口算法当show-page-size小于总页数时组件不会渲染全部页码而是计算一个以当前页为中心的可见窗口Pagination.tsxlet startPage 1; let endPage pageCount; const isMaxSized showPageSize pageCount; if (isMaxSized) { // 当前页置于窗口中间 startPage Math.max(modelValue - Math.floor(showPageSize / 2), 1); endPage startPage showPageSize - 1; // 超出末尾时整体回退 if (endPage pageCount) { endPage pageCount; startPage endPage - showPageSize 1; } }算法要点正常情况下当前页位于窗口正中modelValue - floor(showPageSize/2)贴近首页时用Math.max(..., 1)防止窗口越界贴近末页时先让endPage封顶为pageCount再把startPage回退为endPage - showPageSize 1保证窗口永远完整落在有效页范围内。省略号按钮的生成紧随其后当forceEllipses开启且存在窗口isMaxSized showPageSize 0时若窗口起始页大于 1则在开头插入一个指向startPage - 1的省略号若窗口结束页小于总页数则在末尾插入一个指向endPage 1的省略号。点击省略号即跳转到该目标页等效于整组翻页。边界处理与事件派发所有页码切换统一收敛到updateModelValuePagination.tsxconst updateModelValue (value: number, emitChange?: boolean) { value clamp(value, 1, count.value); if (props.modelValue ! value) { emit(update:modelValue, value); if (emitChange) { emit(change, value); } } };越界保护clamp(value, 1, count.value)将目标页码限制在[1, 总页数]内首屏点上一页、末屏点下一页不会产生无效页码。去重派发仅当目标页码与当前值不同才触发事件避免重复点击造成无意义的状态更新与请求。双向同步watchEffect(() updateModelValue(props.modelValue))监听外部传入的modelValue一旦外部重置页码组件内部状态与渲染随之收敛无需手动刷新。边界禁用上一页按钮在modelValue 1时置为disabled下一页按钮在modelValue count.value时置为disabledPagination.tsx 与 Pagination.tsx保证边界状态下按钮既不可点击、样式也进入禁用态。组件最终渲染为语义化的nav rolenavigation结构内部以ul承载各li项页码按钮带aria-current标记当前页见 Pagination.tsx对屏幕阅读器友好。测试覆盖一览组件的核心行为均有测试保障相关用例位于 packages/vant/src/pagination/test/包括index.spec.ts验证prev-text/next-text/page插槽渲染、change事件按[3, 2, 3]顺序触发、以及showPrevButton/showNextButton为false时按钮 DOM 不渲染demo.spec.ts 与 demo-ssr.spec.ts对完整 demo 页面做快照测试同时覆盖了 SSR 渲染场景保证组件在服务端渲染下输出稳定。小结Vant 的 Pagination 组件用极少的配置覆盖了移动端最常见的分页诉求v-model双向绑定当前页、modesimple压缩展示空间、force-ellipsesshow-page-size解决长列表页码过多问题、插槽体系支持任意按钮内容定制、CSS 变量与 ConfigProvider 支持深度主题定制。理解其总页数优先取 page-count、窗口算法保证可见页码居中且不越界、clamp 收敛 去重派发保证事件稳定的三条实现主线你就能在业务中游刃有余地配置与排查问题。更完整的注册方式说明可参考 组件注册其余组件的使用可继续浏览 vant 组件源码。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价