首页
/ Material UI Pagination 分页组件详解:siblingCount、受控模式、usePagination Hook 与路由集成实战

Material UI Pagination 分页组件详解:siblingCount、受控模式、usePagination Hook 与路由集成实战

2026-09-04 17:59:37作者:幸俭卉

本文以 Material UI(MUI)官方文档 Pagination 组件页 为主体,覆盖从基础用法、页码范围裁剪(siblingCount / boundaryCount)、受控分页、路由集成到无头 Hook usePagination 的完整技术脉络,并结合 Pagination 组件源码 给出每个属性的默认值与底层实现依据,帮助你在博客、电商列表、后台表格等真实场景中正确选择 PaginationTablePagination,并写出可复制运行的分页代码。

组件定位与源码结构

Pagination 组件让用户从一个页面范围中选择特定页码。它适用于「不使用无限加载」时对任意条目列表进行分页的场景,官方文档明确指出:在 SEO 很重要的上下文(例如博客) 中优先使用 Pagination;而对大量表格数据分页,则应使用 TablePagination 组件。

组件的源码位于 packages/mui-material/src/Pagination 目录,核心文件包括:

  • Pagination.js:组件主体,负责将 usePagination 返回的条目映射为 PaginationItem 并管理焦点逻辑;
  • paginationClasses.ts:定义 MuiPagination 的类名工具(rootuloutlinedtext);
  • 配套的无头 Hook usePagination(位于 packages/mui-material/src/usePagination)与条目组件 PaginationItem(位于 packages/mui-material/src/PaginationItem),三者共同构成分页体系的完整分层。

基础用法

最简示例只需 count(总页数)一个必填语义的属性,其余全部有默认值。基础示例见 BasicPagination

import Pagination from '@mui/material/Pagination';

export default function BasicPagination() {
  return <Pagination count={10} />;
}

Pagination.js 源码 中解构出的默认值可以确认各属性缺省行为:

属性 默认值 说明
count 1 总页数
page 当前页(受控),从 1 开始
defaultPage 1 非受控模式下的初始页码
variant 'text' 外观变体,可选 outlined
shape 'circular' 页码按钮形状,可选 rounded
size 'medium' 尺寸,可选 smalllarge
color 'standard' 选中页颜色,支持主题调色板颜色
siblingCount 1 当前页前后各显示几页
boundaryCount 1 首尾固定显示几页
showFirstButton / showLastButton false 是否显示「首页 / 末页」按钮
hidePrevButton / hideNextButton false 是否隐藏「上一页 / 下一页」按钮
renderItem (item) => <PaginationItem {...item} /> 自定义每个分页条目的渲染

外观变体:变体、形状与尺寸

文档提供了三组外观示例,分别对应 variantshapesize 三个属性:

在样式层面,Pagination.js 中根节点被 styled('nav') 定义,overridesResolver 会按 ownerState.variant 叠加 outlined / text 对应的类名;内部 <ul> 固定为 flex 布局、flexWrap: 'wrap'、无列表样式,因此分页天然支持窄容器下的换行展示。

首页 / 末页按钮与隐藏前后翻页按钮

文档的 Buttons 章节说明:可以可选地启用首页、末页按钮,或禁用上一页、下一页按钮。示例见 PaginationButtons,对应属性为 showFirstButtonshowLastButtonhidePrevButtonhideNextButton,四个布尔属性均可自由组合。

一个容易踩的边界情况被源码显式处理了:当你在第 1 页点击「首页/上一页」、或在末页点击「下一页/末页」时,该按钮点击后会变为 disabled。如果此时焦点正停留在该按钮上,焦点会「丢失」,handleItemClick 与焦点恢复逻辑 会把焦点记录到 pendingFocusRef,并在 selectedPage 更新后自动把焦点移到带 aria-current="page" 的选中页上。使用 usePagination 自行渲染时需要注意复刻这一行为。

自定义控制图标

文档说明控制图标(前后翻页箭头)可以自定义,示例见 CustomIcons,通过 showFirstButtonshowLastButton 与自定义 renderItemPaginationItem 的箭头替换为自定义 SVG/图标即可。

页码范围:siblingCount 与 boundaryCount

这是 Pagination 最核心的两个数字属性:

  • siblingCount:控制页码省略号两侧显示的数字个数(相对当前页);
  • boundaryCount:控制首尾页号旁固定显示的页码个数。

官方示例 PaginationRanges 展示了四组组合(count={11}defaultPage={6}):

<Stack spacing={2}>
  <Pagination count={11} defaultPage={6} siblingCount={0} />
  <Pagination count={11} defaultPage={6} /> {/* Default ranges */}
  <Pagination count={11} defaultPage={6} siblingCount={0} boundaryCount={2} />
  <Pagination count={11} defaultPage={6} boundaryCount={2} />
</Stack>

结合默认值 siblingCount=1boundaryCount=1,默认渲染形如 1 … 5 6 7 … 11;将 siblingCount 设为 0 则只剩当前页与边界页,将 boundaryCount 设为 2 则首尾各固定显示两页。这两个参数共同决定了条目数组中 pagestart-ellipsisend-ellipsis 三类条目的分布,其裁剪逻辑全部收敛在 usePagination 内部,组件层只负责渲染。

受控分页

非受控模式下用 defaultPage 指定初始页,onChange 回调签名是 onChange(event, page),其中 page 从 1 开始。受控模式则由外部状态接管,核心写法(对应 PaginationControlled 示例):

export default function PaginationControlled() {
  const [page, setPage] = React.useState(1);

  const handleChange = (event, value) => {
    setPage(value);
  };

  return <Pagination page={page} count={10} onChange={handleChange} />;
}

传入 page 后组件进入受控模式,页码变化只会触发 onChange,需要你在回调中更新状态;Paginationpage prop 从 1 开始编号(源码 PropTypes 注释亦强调这一点,见 Pagination.js)。

路由集成:renderItem + 自定义组件

对于需要把页码写进 URL 的场景(SEO 友好),文档的 Router integration 章节给出了标准做法:通过 renderItemPaginationItemcomponent 换成路由的 Link。完整可运行的 PaginationLink 示例

function Content() {
  const location = useLocation();
  const query = new URLSearchParams(location.search);
  const page = parseInt(query.get('page') || '1', 10);
  return (
    <Pagination
      page={page}
      count={10}
      renderItem={(item) => (
        <PaginationItem
          component={Link}
          to={`/inbox${item.page === 1 ? '' : `?page=${item.page}`}`}
          {...item}
        />
      )}
    />
  );
}

要点:renderItem 接收的每个 item 都携带 pagetypeselectedonClick 等字段,展开为 PaginationItem 的 props 即可;第 1 页的 URL 刻意不带查询参数,保证首页链接干净可分享。

无头 Hook:usePagination

文档明确:usePagination() 是一个无头 Hook,面向高级定制场景暴露,它接受与 Pagination 组件几乎相同的选项,只是去掉了所有与 JSX 渲染相关的 prop;Pagination 组件正是构建在这个 Hook 之上的。

import usePagination from '@mui/material/usePagination';

Hook 的返回值为 { items, ... }items 中每一项的 type 取值包含 firstpreviouspagenextlaststart-ellipsisend-ellipsisUsePagination 官方示例 演示了完全自行渲染:遍历 items,对 start-ellipsis / end-ellipsis 渲染省略号「…」,对 page 类型渲染原生 <button>(选中时加粗),其余类型渲染翻页按钮,并手动实现「点击后按钮禁用时移动焦点到首/末页」的无障碍逻辑——这正是 Pagination.js 中 handleItemClick 所做的事情,说明 Hook 使用者需要自行保证焦点管理的等价行为。

TablePagination:与表格配套的另一种分页

文档特别提示:为大型表格数据分页应使用 TablePagination 组件,可参考文档 table 章节的 custom pagination options 内容。两者最关键的差异在页码起点:

  • Paginationpage1 开始,以匹配「页码要出现在 URL 中」的需求;
  • TablePaginationpage0 开始,以匹配渲染大量表格数据时零基 JavaScript 数组切片的需求(items.slice(page * rowsPerPage, ...))。

因此在混合使用两个组件时,务必做 page 的 ±1 换算,这是实际项目中最常见的 off-by-one 错误来源。

无障碍(Accessibility)

文档的 Accessibility 章节包含两部分,均已在源码中得到印证:

ARIA:根节点默认带有 role="navigation"(源码中即渲染为 <nav>)和 aria-label="pagination navigation"(见 Pagination.js 第 158 行);每个分页条目都会获得说明其用途的 aria-label,例如 "go to first page"、"go to previous page"、"go to page 1"。这些文案默认由 defaultGetAriaLabel 生成:type === 'page' 时返回 Go to page N(选中页则无前缀 Go to),其他类型返回 Go to ${type} page。可本地化的文案可通过 getItemAriaLabel prop 覆盖,其签名为 (type, page, selected) => string

键盘:分页条目处于 Tab 顺序中,tabindex 为 "0",配合上文提到的焦点恢复逻辑,键盘用户在翻页后焦点会稳定落在新的选中页上。

样式类名与定制

paginationClasses.ts 导出了 MuiPagination 的全部类名:root(根元素)、ul(列表容器)、outlinedvariant="outlined" 时)、textvariant="text" 时),可配合 sxclasses prop 或主题 components.MuiPagination.styleOverrides 做样式覆盖。

小结

Material UI 的 Pagination 以「组件 + 无头 Hook」双层设计覆盖从开箱即用到完全自渲染的分页需求:variant / shape / size / color 控制外观,siblingCount / boundaryCount 控制页码范围,showFirstButton / showLastButton / hidePrevButton / hideNextButton 控制导航按钮,renderItem 打通路由集成,usePagination 则把条目计算逻辑开放给定制场景;而表格数据分页请切换到 TablePagination 并注意两者页码起点(1 基 vs 0 基)的差异。所有属性默认值均可在 packages/mui-material/src/Pagination/Pagination.js 中逐一对应验证。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341