跳转到内容

Pagination 分页 ​

用于在分页结果之间导航。

用法 ​

在页码之间导航

组件结构 ​

加粗的是必需部件。

data-scope="pagination":root · summary · jumper · prev-trigger · next-trigger · item · ellipsis-trigger · page-size-select · positioner · content

示例 ​

尺寸 ​

适配不同的界面密度

小
中
大

简洁模式 ​

只显示上一页、当前页与下一页

快速跳页 ​

输入页码后按 Enter 跳转

每页条数 ​

调整每页展示数量

展开省略位 ​

查看被折叠的页码

设计指引 ​

何时使用 ​

  • 结果总数已知,需要跳转到指定页。
  • 用户需要确认当前位置与剩余页数。

何时不用 ​

  • 连续加载的内容流,使用无限滚动。
  • 数据量较少,无需分页。

特性 ​

  • count 表示总条数,pageSize 表示每页条数。
  • siblingCount 控制当前页两侧展示的页码数量。
  • 支持上一页、下一页、跳页、每页数量与可展开省略位。
  • 更改 pageSize 后自动重算总页数并校正当前页。

组合 ​

  • summary 显示当前结果范围。
  • jumper 用于输入页码并按 Enter 跳转。
  • page-size-select 提供每页数量选择。

最佳实践 ​

  • 将当前页同步到地址,便于刷新和分享。
  • 数据加载期间保留分页器,避免布局跳动。

反模式 ​

  • 不要将 count 当作总页数。
  • 不要在结果很少时使用分页。

API 参考 ​

产物 ​

层值
自定义元素<xh-pagination>
Vue 组件XhPaginationContent XhPaginationEllipsisTrigger XhPaginationItem XhPaginationJumper XhPaginationNextTrigger XhPaginationPageSizeSelect XhPaginationPositioner XhPaginationPrevTrigger XhPaginationRoot XhPaginationSummary
组合式函数usePagination
状态机paginationMachine
皮肤@xihan-ui/styles/pagination.css

Props ​

属性类型必填说明
countnumber总条数(不是总页数)。总页数由它与 pageSize 计算。
pageSizenumber每页条数,默认 10;小于 1 的值一律按 1 处理。提供即受控,语义同 page。
defaultPageSizenumber非受控初始每页条数,默认 10。
pageSizeOptionsnumber[]可选的每页条数档位,默认 [10, 20, 50, 100]。只做取值来源,不决定长相。
pagenumber当前页。提供即受控:内部不再自行修改,只发 onPageChange。
defaultPagenumber非受控初始页,默认 1。
siblingCountnumber当前页两侧各显示的页数,默认 1。
dirDirection文字方向,只作用于排版;上一页 / 下一页的语义不随之翻转,上一页永远是 page - 1。
translationsPartial<PaginationTranslations>
placementPlacement省略位展开后的落点,默认 bottom-start(列表类浮层)。
offsetnumber浮层与省略位之间的间距(px),默认 8。
openDelaynumber指针停在省略位多久后才展开(ms),默认 200;只收有限非负数。
closeDelaynumber指针离开后多久收起(ms),默认 300:留出斜向划入浮层的时间;只收有限非负数。
toneTone语气:brand / neutral / success / warning / danger / info,决定使用哪族颜色。
sizeSize尺寸:sm / md / lg。
onPageChange(details: PaginationPageChangeDetails) => void页码变化意图回调;受控时是唯一出口,非受控时随内部写入一并通知。
onPageSizeChange(details: PaginationPageSizeChangeDetails) => void每页条数变化意图回调,语义同上;一并给出换算后的页码。

事件 ​

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
page-changePaginationPageChangeDetails页码变化;detail 为 { page: number, pageSize: number }
page-size-change``每页条数变化;detail 为 { pageSize: number, page: number },页码是换算后的

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhPaginationContentdefault{ pages: number[] }
XhPaginationRootdefaultPaginationRootSlotProps
XhPaginationSummarydefault{ summaryText: string, start: number, end: number, count: number }

React 适配器 props ​

只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。

React 组件属性类型必填说明
XhPaginationContentchildrenSlotChildren<PaginationContentSlotProps>
XhPaginationEllipsisTriggersidePaginationEllipsisSide该省略位所在的一侧:首页与窗口之间是 start,窗口与末页之间是 end。
XhPaginationItemvaluenumber | string是该项对应的页码,兼收字符串。
XhPaginationPageSizeSelectcontainer() => Element | null浮层挂载的容器;未提供时按全局配置,再未提供时挂载到 body。
XhPaginationPositionercontainer() => Element | null浮层挂载的容器;未提供时按全局配置,再未提供时挂载到 body。
XhPaginationRootchildrenSlotChildren<PaginationRootSlotProps>
XhPaginationSummarychildrenSlotChildren<PaginationSummarySlotProps>

状态 ​

公开状态写入 data-state。

部件取值
ellipsis-trigger'open' | 'closed'
positioner'open' | 'closed'
content'open' | 'closed'

以下名称仅用于内部状态机。

状态:closed · opening · visible · visible.open · visible.closing

事件:PAGE.SET · PAGE_SIZE.SET · PAGE.PREV · PAGE.NEXT · ELLIPSIS.ENTER · ELLIPSIS.LEAVE · ELLIPSIS.TOGGLE · ELLIPSIS.CLOSE · after.openDelay · after.closeDelay · PRESS.START · PRESS.END

判据:isSameEllipsis · canPress

connect API ​

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
pagenumber当前页,恒在 [1, max(totalPages, 1)] 内。
pageSizenumber
pageSizeOptionsnumber[]可选的每页条数档位,默认 [10, 20, 50, 100];已按升序去重并夹到至少 1。
countnumber
totalPagesnumber
pagesPaginationPage[]页码序列,作者按它渲染 item 与 ellipsis-trigger。
pageItemsPaginationPageItem[]同一序列,但省略位附带被折叠的页码:展开省略号需要使用它。
openEllipsisPaginationEllipsisSide | null当前展开的是哪一侧的省略位;未展开时为 null。
pageRangePaginationEntryRange当前页对应的条目区间,1 基闭区间;无数据时是 { start: 0, end: 0 }。
summaryTextstring信息区文本,由 translations.summary 与 pageRange / count 算出。
previousPagenumber | null上一页页码;已在首页(或无数据)时为 null。
nextPagenumber | null
setPage(page: number) => void页码会被夹进合法区间,越界入参不会写出越界的页。
goToPrevPage() => void
goToNextPage() => void
setPageSize(pageSize: number) => void更换每页条数:页码随之换算,使改档前的第一条仍留在页内。
slice<V>(data: readonly V[]) => V[]按当前页从整份数据中切出该页。
getRootProps() => T['element']
getSummaryProps() => T['element']信息区容器;文本由作者放置,默认使用 api.summaryText。
getJumperProps() => T['input']跳页输入框:输入页码按回车即跳转,越界值由 setPage 夹回合法区间。
getPrevTriggerProps() => T['button']
getNextTriggerProps() => T['button']
getItemProps(props: PaginationItemProps) => T['button']
getEllipsisTriggerProps(props: PaginationEllipsisTriggerProps) => T['button']省略位:可展开的按钮,展开后列出被折叠的页码。
getPageSizeSelectProps() => T['element']每页条数控制器的挂载点:只负责排布的一格,控件本体是内嵌下拉的角色节点。
pageSizeSelectSelectApi<T>每页条数的下拉,整份 select 的 api。档位由 collection 给出(文字取 translations.pageSizeOption),选中值即当前每页条数;作者按它渲染 select 的角色节点。
getPositionerProps() => T['element']
getContentProps() => T['element']
closeEllipsis() => void收起展开的省略位。

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Enter / Spacefocus in item跳到该页码(原生按钮激活,平台把按键翻成 click)
Enter / Spacefocus in prev-trigger, 非首页回上一页;首页时按钮是原生 disabled,焦点根本落不上去
Enter / Spacefocus in next-trigger, 非末页进下一页;末页时按钮是原生 disabled
Enter / Spacefocus in ellipsis-trigger摊开被折叠的那几页;再按一次收起。纯悬停会把键盘用户挡在外面,而那几页除了这里没有别的入口
Enter / Spaceheld in prev-trigger / next-trigger / item / ellipsis-trigger, 该钮未禁用按住期间该钮投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下,摊开面板收起时面板里被按住的页码也撤下。到边界的翻页钮是原生 disabled,不进按压面
Escapeellipsis-trigger 已摊开收起摊开的页码面板(走消解层,点面板外面同样收起)
Tab / Shift+Tabfocus in root逐个经过每个可用按钮:分页不做 roving tabindex,用户要能 Tab 到某一页再确认;禁用的首尾按钮自动脱离序列

ARIA ​

以下属性由 connect 生成。

部件属性值
rootaria-labellabel.root
jumperaria-labellabel.jumper
prev-triggeraria-labellabel.prevTrigger
next-triggeraria-labellabel.nextTrigger
itemaria-current'page' | undefined
itemaria-labellabel.item(item.page)
ellipsis-triggeraria-controlscontent 部件的 id | undefined
ellipsis-triggeraria-expanded'true' | 'false'
ellipsis-triggeraria-haspopup'true'
ellipsis-triggeraria-labellabel.ellipsis( (items.find(item => item.type === 'el…
contentaria-hidden!open || undefined
contentaria-labellabel.ellipsis(folded.length)
contentrole'group'

样式参考 ​

皮肤 ​

@xihan-ui/styles/pagination.css 使用 [data-scope="pagination"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides。

数据属性 ​

由 connect 生成;条件不成立时不输出无值属性。

部件属性值
rootdata-empty''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
summarydata-empty''(条件成立时才出现)
jumperdata-empty''(条件成立时才出现)
prev-triggerdata-disabled''(条件成立时才出现)
prev-triggerdata-pressed''(条件成立时才出现)
prev-triggerdata-xh-action-control''
prev-triggerdata-xh-action-display'always'
prev-triggerdata-xh-action-profile'text'
prev-triggerdata-xh-action-sizeprops.size
prev-triggerdata-xh-action-variant'ghost'
next-triggerdata-disabled''(条件成立时才出现)
next-triggerdata-pressed''(条件成立时才出现)
next-triggerdata-xh-action-control''
next-triggerdata-xh-action-display'always'
next-triggerdata-xh-action-profile'text'
next-triggerdata-xh-action-sizeprops.size
next-triggerdata-xh-action-variant'ghost'
itemdata-current''(条件成立时才出现)
itemdata-pressed''(条件成立时才出现)
itemdata-xh-action-control''
itemdata-xh-action-display'always'
itemdata-xh-action-profile'text'
itemdata-xh-action-sizeprops.size
itemdata-xh-action-variant'ghost'
ellipsis-triggerdata-pressed''(条件成立时才出现)
ellipsis-triggerdata-sideprops.side
ellipsis-triggerdata-state'open' | 'closed'
ellipsis-triggerdata-xh-action-control''
ellipsis-triggerdata-xh-action-display'always'
ellipsis-triggerdata-xh-action-profile'text'
ellipsis-triggerdata-xh-action-sizeprops.size
ellipsis-triggerdata-xh-action-variant'ghost'
page-size-selectdata-empty''(条件成立时才出现)
positionerdata-hidden''(条件成立时才出现)
positionerdata-placement定位引擎算出的实际落位
positionerdata-positioned''(条件成立时才出现)
positionerdata-sizeprops.size
positionerdata-state'open' | 'closed'
positionerdata-toneprops.tone
contentdata-placement定位引擎算出的实际落位
contentdata-sizeprops.size
contentdata-state'open' | 'closed'

CSS 变量 ​

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-pagination-content-bgcontentbackgrounddefault--xh-bg-surfacepagination 的 content 部件 background 覆盖槽。
--xh-pagination-content-bordercontentborderdefault--xh-border-defaultpagination 的 content 部件 border 覆盖槽。
--xh-pagination-content-max-hcontentmax-block-sizedefault--xh-overlay-max-hpagination 的 content 部件 max-block-size 覆盖槽。
--xh-pagination-content-max-wcontentmax-inline-sizedefault--xh-overlay-max-wpagination 的 content 部件 max-inline-size 覆盖槽。
--xh-pagination-content-pcontentpaddingdefault--xh-space-1pagination 的 content 部件 padding 覆盖槽。
--xh-pagination-content-radiuscontentborder-radiusdefault--xh-shape-overlaypagination 的 content 部件 border-radius 覆盖槽。
--xh-pagination-content-shadowcontentbox-shadowdefault--xh-elevation-floatingpagination 的 content 部件 box-shadow 覆盖槽。
--xh-pagination-ellipsis-trigger-fgellipsis-triggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-fg-subtlepagination 的 ellipsis-trigger 部件 color 覆盖槽。
--xh-pagination-font-sizeellipsis-trigger
item
jumper
next-trigger
prev-trigger
summary
font-sizedefault--xh-_pagination-font-sizepagination 的 ellipsis-trigger、item、jumper、next-trigger、prev-trigger、summary 部件 font-size 覆盖槽。
--xh-pagination-gapcontent
root
gapdefault--xh-space-1pagination 的 content、root 部件 gap 覆盖槽。
--xh-pagination-icon-sizeellipsis-trigger
item
next-trigger
positioner
prev-trigger
root
--xh-icon-sizedefault
is([data-part='root'], [data-part='positioner'])
size=lg
size=sm
--xh-_action-profile-glyph-size
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
pagination 的 ellipsis-trigger、item、next-trigger、positioner、prev-trigger、root 部件 --xh-icon-size 覆盖槽。
--xh-pagination-item-bgellipsis-trigger
item
next-trigger
prev-trigger
--xh-ink-surface
background-color
default
xh-ink-surface
--xh-_action-variant-bg-restpagination 的 ellipsis-trigger、item、next-trigger、prev-trigger 部件 --xh-ink-surface、background-color 覆盖槽。
--xh-pagination-item-bg-activeellipsis-trigger
item
next-trigger
prev-trigger
background-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-pressedpagination 的 ellipsis-trigger、item、next-trigger、prev-trigger 部件 background-color 覆盖槽。
--xh-pagination-item-bg-hoverellipsis-trigger
item
next-trigger
prev-trigger
background-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverpagination 的 ellipsis-trigger、item、next-trigger、prev-trigger 部件 background-color 覆盖槽。
--xh-pagination-item-bg-selecteditem--xh-ink-surface
background-color
current
focus-visible
xh-ink-surface
--xh-_pagination-selected-bgpagination 的 item 部件 --xh-ink-surface、background-color 覆盖槽。
--xh-pagination-item-bg-selected-activeitembackground-colorcurrent
disabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_pagination-selected-bg-activepagination 的 item 部件 background-color 覆盖槽。
--xh-pagination-item-bg-selected-hoveritembackground-colorcurrent
disabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_pagination-selected-bg-hoverpagination 的 item 部件 background-color 覆盖槽。
--xh-pagination-item-border-selecteditemborder
border-color
current
focus-visible
--xh-_pagination-selected-bgpagination 的 item 部件 border、border-color 覆盖槽。
--xh-pagination-item-border-selected-activeitemborder-colorcurrent
disabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_pagination-selected-bg-activepagination 的 item 部件 border-color 覆盖槽。
--xh-pagination-item-border-selected-hoveritemborder-colorcurrent
disabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_pagination-selected-bg-hoverpagination 的 item 部件 border-color 覆盖槽。
--xh-pagination-item-fgellipsis-trigger
item
jumper
next-trigger
prev-trigger
colordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
--xh-fg-default
pagination 的 ellipsis-trigger、item、jumper、next-trigger、prev-trigger 部件 color 覆盖槽。
--xh-pagination-item-fg-selecteditemcolorcurrent
disabled
focus-visible
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_pagination-selected-fgpagination 的 item 部件 color 覆盖槽。
--xh-pagination-item-font-weightellipsis-trigger
item
next-trigger
prev-trigger
font-weightdefault--xh-text-label-weightpagination 的 ellipsis-trigger、item、next-trigger、prev-trigger 部件 font-weight 覆盖槽。
--xh-pagination-item-hellipsis-trigger
item
jumper
next-trigger
prev-trigger
summary
block-sizedefault--xh-_pagination-item-sizepagination 的 ellipsis-trigger、item、jumper、next-trigger、prev-trigger、summary 部件 block-size 覆盖槽。
--xh-pagination-item-min-sizeellipsis-trigger
item
next-trigger
prev-trigger
min-inline-sizedefault--xh-_pagination-item-sizepagination 的 ellipsis-trigger、item、next-trigger、prev-trigger 部件 min-inline-size 覆盖槽。
--xh-pagination-item-pxellipsis-trigger
item
jumper
next-trigger
prev-trigger
padding-inlinedefault--xh-_pagination-item-pxpagination 的 ellipsis-trigger、item、jumper、next-trigger、prev-trigger 部件 padding-inline 覆盖槽。
--xh-pagination-item-radiusellipsis-trigger
item
jumper
next-trigger
prev-trigger
border-radiusdefault--xh-shape-controlpagination 的 ellipsis-trigger、item、jumper、next-trigger、prev-trigger 部件 border-radius 覆盖槽。
--xh-pagination-item-shadowitembox-shadowcurrent
disabled
focus-visible
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
nonepagination 的 item 部件 box-shadow 覆盖槽。
--xh-pagination-jumper-bgjumperbackgrounddefault--xh-bg-surfacepagination 的 jumper 部件 background 覆盖槽。
--xh-pagination-jumper-bg-hoverjumperbackgroundhover
not(:disabled)
--xh-bg-subtle-hoverpagination 的 jumper 部件 background 覆盖槽。
--xh-pagination-jumper-borderjumperborderdefault--xh-border-defaultpagination 的 jumper 部件 border 覆盖槽。
--xh-pagination-jumper-border-hoverjumperborder-colorhover
not(:disabled)
--xh-border-strongpagination 的 jumper 部件 border-color 覆盖槽。
--xh-pagination-jumper-wjumperinline-sizedefault--xh-space-8pagination 的 jumper 部件 inline-size 覆盖槽。
--xh-pagination-layerpositionerz-indexdefault--xh-_layerpagination 的 positioner 部件 z-index 覆盖槽。
--xh-pagination-summary-fgsummarycolordefault--xh-fg-mutedpagination 的 summary 部件 color 覆盖槽。

动效 ​

动效角色:按压 · 状态 · 出现(锚定面板) · 出现(无锚定弹出)(见动效规范)。

共享关键帧 xh-pop-in · xh-pop-out 由 family/motion.css 提供,皮肤 @import 它,单独引入仍成立;background-color · border-color 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

皮肤之外还有一段:退场由适配器的退场闸门把关,动画播完才真收起。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

响应式 ​

皮肤另按输入能力分档:pointer: coarse:同一份皮肤在触屏与带指针的设备上不一样,与视口宽度无关。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像;另有按 dir 分支的规则。

Released under The MIT License