usePagination
一个分页状态管理 Hook,提供完整的分页功能,包括页码跳转、每页大小调整、分页信息计算等。支持响应式数据源和丰富的回调机制。
基础用法
📄 基础分页功能
基础分页
1 / 10
跳转到:
当前页: 1
每页大小: 10
总数据量: 95
总页数: 10
数据范围: 1 - 10
每页大小调整
每页显示:总共 127 条数据
...
当前显示: 第 1 - 10 条,共 127 条
数据表格示例
高级用法
🚀 高级分页功能
响应式数据源
模拟数据量:
1 / 10
响应式总数: 150 条
当前页码: 1
总页数: 10
带回调的分页
1 / 9
回调日志:
无限滚动模拟
已加载:1 页 / 10 条
📄 数据项 #1
📄 数据项 #2
📄 数据项 #3
📄 数据项 #4
📄 数据项 #5
📄 数据项 #6
📄 数据项 #7
📄 数据项 #8
📄 数据项 #9
📄 数据项 #10
总数据: 100 条
已加载: 10 条
加载进度: 10%
API 参考
参数
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
options | UsePaginationOptions | {} | 配置选项 |
UsePaginationOptions
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
initialPage | number | 1 | 初始页码 |
initialPageSize | number | 10 | 初始每页大小 |
total | number | Ref<number> | 0 | 总数据量 |
pageSizeOptions | number[] | [10, 20, 50, 100] | 可选的每页大小选项 |
onPageChange | (page: number) => void | - | 页码变化回调 |
onPageSizeChange | (pageSize: number) => void | - | 每页大小变化回调 |
onChange | (page: number, pageSize: number) => void | - | 分页信息变化回调 |
返回值
usePagination
返回一个包含分页信息和操作方法的数组:
typescript
const [paginationInfo, actions] = usePagination(options);
索引 | 名称 | 类型 | 说明 |
---|---|---|---|
0 | paginationInfo | ComputedRef<PaginationInfo> | 分页信息 |
1 | actions | PaginationActions | 分页操作方法 |
PaginationInfo
属性 | 类型 | 说明 |
---|---|---|
current | number | 当前页码 |
pageSize | number | 每页大小 |
total | number | 总数据量 |
totalPages | number | 总页数 |
hasPrev | boolean | 是否有上一页 |
hasNext | boolean | 是否有下一页 |
startIndex | number | 当前页开始索引(从 0 开始) |
endIndex | number | 当前页结束索引(从 0 开始) |
PaginationActions
方法 | 类型 | 说明 |
---|---|---|
goToPage | (page: number) => void | 跳转到指定页 |
prev | () => void | 上一页 |
next | () => void | 下一页 |
first | () => void | 第一页 |
last | () => void | 最后一页 |
setPageSize | (pageSize: number) => void | 设置每页大小 |
setTotal | (total: number) => void | 设置总数据量 |
reset | () => void | 重置分页 |
类型定义
typescript
export interface UsePaginationOptions {
initialPage?: number;
initialPageSize?: number;
total?: number | Ref<number>;
pageSizeOptions?: number[];
onPageChange?: (page: number) => void;
onPageSizeChange?: (pageSize: number) => void;
onChange?: (page: number, pageSize: number) => void;
}
export interface PaginationInfo {
current: number;
pageSize: number;
total: number;
totalPages: number;
hasPrev: boolean;
hasNext: boolean;
startIndex: number;
endIndex: number;
}
export interface PaginationActions {
goToPage: (page: number) => void;
prev: () => void;
next: () => void;
first: () => void;
last: () => void;
setPageSize: (pageSize: number) => void;
setTotal: (total: number) => void;
reset: () => void;
}
export type UsePaginationReturn = [ComputedRef<PaginationInfo>, PaginationActions];
export function usePagination(options?: UsePaginationOptions): UsePaginationReturn;
使用场景
- 数据表格 - 大量数据的分页显示
- 列表组件 - 长列表的分页浏览
- 搜索结果 - 搜索结果的分页展示
- 无限滚动 - 配合无限滚动实现数据加载
- API 分页 - 配合后端 API 实现服务端分页
- 前端分页 - 前端数据的客户端分页
高级用法
服务端分页
typescript
const total = ref(0);
const loading = ref(false);
const data = ref([]);
const [pagination, actions] = usePagination({
initialPageSize: 20,
total,
onPageChange: async (page) => {
await loadData(page, pagination.value.pageSize);
},
onPageSizeChange: async (pageSize) => {
await loadData(1, pageSize);
},
});
const loadData = async (page: number, pageSize: number) => {
loading.value = true;
try {
const response = await api.getData({ page, pageSize });
data.value = response.data;
total.value = response.total;
} finally {
loading.value = false;
}
};
前端分页
typescript
const allData = ref([
/* 所有数据 */
]);
const [pagination, actions] = usePagination({
initialPageSize: 10,
total: computed(() => allData.value.length),
});
// 当前页数据
const currentPageData = computed(() => {
const { startIndex, endIndex } = pagination.value;
return allData.value.slice(startIndex, endIndex + 1);
});
搜索结果分页
typescript
const searchKeyword = ref("");
const filteredData = computed(() => {
return allData.value.filter((item) => item.name.includes(searchKeyword.value));
});
const [pagination, actions] = usePagination({
total: computed(() => filteredData.value.length),
});
// 搜索时重置到第一页
watch(searchKeyword, () => {
actions.goToPage(1);
});
无限滚动
typescript
const loadedData = ref([]);
const [pagination, actions] = usePagination({
initialPageSize: 20,
total: 1000,
});
const loadMore = async () => {
if (pagination.value.hasNext) {
const newData = await fetchData(pagination.value.current + 1);
loadedData.value.push(...newData);
actions.next();
}
};
// 滚动到底部时自动加载
const { arrivedState } = useScroll(scrollContainer);
watch(
() => arrivedState.bottom,
(isBottom) => {
if (isBottom) {
loadMore();
}
},
);
URL 同步
typescript
const route = useRoute();
const router = useRouter();
const [pagination, actions] = usePagination({
initialPage: Number(route.query.page) || 1,
initialPageSize: Number(route.query.pageSize) || 10,
onChange: (page, pageSize) => {
router.push({
query: { ...route.query, page, pageSize },
});
},
});
注意事项
- 页码从 1 开始计算,索引从 0 开始计算
- 当总数据量变化时,会自动调整当前页码
- 设置每页大小时会智能计算新的页码位置
- 响应式 total 参数支持动态数据源
- 所有操作都会触发相应的回调函数
- 重置操作会恢复到初始状态
- 跳转页码会自动限制在有效范围内