import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationBasicDemo() {
const [page, setPage] = useState(1);
return (
<Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />
);
}安装
桶式导出
import { Pagination } from "@cloudflare/kumo";细粒度导入
import { Pagination } from "@cloudflare/kumo/components/pagination";用法
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export default function Example() {
const [page, setPage] = useState(1);
return (
<Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />
);
}示例
完整控件(默认)
默认分页包含首页、上一页、页码输入、 下一页和末页按钮。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationFullDemo() {
const [page, setPage] = useState(1);
return (
<Pagination
page={page}
setPage={setPage}
perPage={10}
totalCount={100}
controls="full"
/>
);
}简易控件
使用 controls="simple" 实现最简分页,
仅保留上一页和下一页按钮。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationSimpleDemo() {
const [page, setPage] = useState(1);
return (
<Pagination
page={page}
setPage={setPage}
perPage={10}
totalCount={100}
controls="simple"
/>
);
}未知总数
当数据源不返回总条数时,使用 hasNextPage。这在基于游标的 API 中
很常见,因为计算总数代价高昂或根本不可用。根据响应中的下一页信号
设置该值,只在还存在下一组结果时保持
「下一页」可用。
没有总数时,用户只能顺序翻页,因此 Pagination 会隐藏首页、末页和
页码选择控件。此时 page 值仍可用于界面展示,但你的应用
需要自行保存并随每次请求发送游标
或续页令牌。
const [page, setPage] = useState(1);
const { data } = useQuery({
queryKey: ["events", page],
queryFn: () => getEvents({ cursor: cursors[page - 1] }),
});
return (
<Pagination
page={page}
setPage={setPage}
hasNextPage={data.hasMore}
text={() => `Page ${page}`}
/>
);import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination for an API that reports whether another page exists, but not a total. */
export function PaginationUnknownTotalDemo() {
const [page, setPage] = useState(1);
const hasNextPage = page < 3;
return (
<Pagination
text={() => `Page ${page}`}
page={page}
setPage={setPage}
hasNextPage={hasNextPage}
/>
);
}中间页状态
处于数据集中间位置、所有导航均已启用的分页。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationMidPageDemo() {
const [page, setPage] = useState(5);
return (
<Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />
);
}空结果
当 totalCount={0} 时,Pagination 会显示一个空页面,且 setPage
永远不会以页码 0 被调用。在第 1 页时,所有导航按钮均被禁用。如果结果可能在
后续页面变为空(例如经过筛选后),请将 page 重置为 1。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** An empty result set renders a single empty page with navigation disabled. */
export function PaginationEmptyDemo() {
const [page, setPage] = useState(1);
return (
<Pagination page={page} setPage={setPage} perPage={10} totalCount={0} />
);
}页码输入
页码输入框接受整数页码。按 Enter 或将焦点移出即可跳转到该页。超出范围的数字
会跳转到第一页或最后一页。其他内容,例如 abc、2.5 或 1e1,会在不调用
setPage 的情况下恢复为当前页。
大数据集
Pagination 可以处理包含大量页数的数据集。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationLargeDatasetDemo() {
const [page, setPage] = useState(1);
return (
<Pagination page={page} setPage={setPage} perPage={25} totalCount={1250} />
);
}自定义文本
你可以设置自定义的分页文本。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
export function PaginationCustomTextDemo() {
const [page, setPage] = useState(1);
return (
<Pagination
text={({ perPage }: { perPage?: number }) =>
`Page ${page} - showing ${perPage} per page`
}
page={page}
setPage={setPage}
perPage={25}
totalCount={100}
/>
);
}组合组件
如需更灵活地控制布局和功能,可以使用组合组件 API,按任意顺序组合 Pagination.Info、Pagination.PageSize、Pagination.Controls 和 Pagination.Separator。
每页条数选择器
添加下拉框,让用户选择每页显示的项目数量。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination with a page size selector using compound components. */
export function PaginationPageSizeSelectorDemo() {
const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(25);
return (
<Pagination
page={page}
setPage={setPage}
perPage={perPage}
totalCount={500}
>
<Pagination.Info />
<Pagination.Separator />
<Pagination.PageSize
value={perPage}
onChange={(size) => {
setPerPage(size);
setPage(1);
}}
/>
<Pagination.Controls />
</Pagination>
);
}自定义每页条数选项
使用 options 属性自定义可选的每页条数,默认值为
[25, 50, 100, 250]。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination with custom page size options using compound components. */
export function PaginationCustomPageSizeOptionsDemo() {
const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(10);
return (
<Pagination
page={page}
setPage={setPage}
perPage={perPage}
totalCount={200}
>
<Pagination.Info />
<Pagination.Separator />
<Pagination.PageSize
value={perPage}
onChange={(size) => {
setPerPage(size);
setPage(1);
}}
options={[10, 20, 50]}
/>
<Pagination.Controls />
</Pagination>
);
}自定义信息文本
使用渲染函数自定义信息文本。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination with custom info text using compound components. */
export function PaginationCompoundCustomInfoDemo() {
const [page, setPage] = useState(1);
return (
<Pagination page={page} setPage={setPage} perPage={25} totalCount={100}>
<Pagination.Info>
{({ page, totalCount }) =>
`Page ${page} of ${Math.ceil((totalCount ?? 1) / 25)}`
}
</Pagination.Info>
<Pagination.Controls />
</Pagination>
);
}自定义布局
可按任意顺序排列组件。这里将每页条数选择器放在了右侧。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination with page size selector on the right side. */
export function PaginationPageSizeRightDemo() {
const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(25);
return (
<Pagination
page={page}
setPage={setPage}
perPage={perPage}
totalCount={500}
>
<Pagination.Info />
<div className="flex items-center gap-2">
<Pagination.Controls />
<Pagination.Separator />
<Pagination.PageSize
value={perPage}
onChange={(size) => {
setPerPage(size);
setPage(1);
}}
/>
</div>
</Pagination>
);
}下拉页码选择器
在 Pagination.Controls 上设置 pageSelector="dropdown",即可用下拉选择
替代文本输入进行页码导航。当你希望用户从可用页码列表中选择,而不是输入数字时,
这会很有用。
<Pagination page={page} setPage={setPage} perPage={perPage} totalCount={500}>
<Pagination.Info />
<Pagination.Separator />
<Pagination.PageSize
value={perPage}
onChange={(size) => {
setPerPage(size);
setPage(1);
}}
/>
<Pagination.Controls pageSelector="dropdown" />
</Pagination>国际化
使用 labels 属性自定义面向不同 locale 的所有界面字符串。所有标签默认均为英文。
import { useState } from "react";
import { Pagination } from "@cloudflare/kumo";
/** Pagination with French labels for internationalization. */
export function PaginationI18nDemo() {
const [page, setPage] = useState(1);
return (
<Pagination
page={page}
setPage={setPage}
perPage={10}
totalCount={100}
labels={{
firstPage: "Première page",
previousPage: "Page précédente",
nextPage: "Page suivante",
lastPage: "Dernière page",
pageNumber: "Numéro de page",
pageSize: "Taille de page",
}}
>
<Pagination.Info>
{({ pageShowingRange, totalCount }) => (
<>
Affichage de{" "}
<span className="tabular-nums">{pageShowingRange}</span> sur{" "}
<span className="tabular-nums">{totalCount}</span>
</>
)}
</Pagination.Info>
<Pagination.Controls />
</Pagination>
);
}API 参考
| Prop | Type | Default | Description |
|---|---|---|---|
| setPage* | (page: number) => void | - | 页面变化时的回调 |
| page | number | - | 当前页码(从 1 开始)。 |
| perPage | number | - | 每页显示的条目数。 |
| totalCount | number | - | 所有页面的总项目数。 |
| hasNextPage | boolean | - | 当总数未知时,是否存在另一页。提供 |
| className | string | - | 容器的额外 CSS 类 |
| labels | PaginationLabels | - | 用于 aria-labels 国际化的标签。所有标签都有英文默认值。 对于如 "Showing X of Y" 之类的可见文本,请在子组件上使用渲染属性:
|
| children | ReactNode | - | 用于自定义布局的复合组件子元素。使用 |
| controls | "full" | "simple" | "full" | - |
| text | object | - | - |