封装通用分页hook:管理currentpage、pagesize、total、data、isfetching状态及search、refresh、oncurrentchange、onsizechange操作,解耦请求逻辑,支持transform适配接口格式、自动清理副作用与防抖。

封装一个通用的分页器响应式状态管理 Hook,核心是把 页码、页大小、总数、当前数据、加载态 这些强关联的状态和操作(搜索、刷新、翻页、改页大小)打包成一个可复用单元,同时与请求逻辑解耦、支持配置、自动清理副作用。
明确职责边界:分页状态 + 分页行为
分页 Hook 不直接发请求,而是接收一个请求函数(如 getOrderList),负责管理参数传递、响应解析、状态同步。它应返回:
- 响应式状态:currentPage、pageSize、total、data、isFetching
- 控制方法:search(带参数重置页码并请求)、refresh(不重置参数只重拉当前页)、onCurrentChange、onSizeChange
- 可选能力:自动初始化请求(initFetch)、默认查询参数(params)、错误统一处理、防抖(如搜索框)
约定接口返回格式,简化适配逻辑
让后端或 API 层统一返回标准分页结构,Hook 内部就能免去大量字段映射。推荐格式:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
若实际接口字段不同(比如 data.list / data.count),可在调用时通过 transform 回调做一次转换,不污染 Hook 主体逻辑。
实现关键点:状态联动与副作用控制
分页不是孤立变量,它们之间有强约束关系:
- 调用
search(params)时,必须重置currentPage = 1,再触发请求 -
onCurrentChange(page)只改页码,不重置其他参数;onSizeChange(size)同理 - 组件卸载时,需取消未完成的请求(配合 axios CancelToken 或 AbortController)
- 避免重复请求:当
currentPage或pageSize变化时,若上一次请求未完成,应中止它
代码结构示意(精简版)
文件路径:src/hooks/usePageFetch.ts
import { useRequest } from './useRequest' // 基础请求 Hook
export function usePageFetch
apiFn: (params: any) => Promise,
options: {
initFetch?: boolean;
params?: Record
transform?: (res: any) => { list: T[]; total: number };
} = {}
) {
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const data = ref
const isFetching = ref(false)
const { run, loading, error, data: rawData } = useRequest(apiFn, {
manual: true,
onSuccess: (res) => {
const parsed = options.transform ? options.transform(res) : res
data.value = parsed.list
total.value = parsed.total
}
})
// 同步 loading 状态
watch(loading, v => isFetching.value = v)
const search = (params: Record
currentPage.value = 1
run({ ...options.params, ...params })
}
const refresh = () => run({ ...options.params, page: currentPage.value, size: pageSize.value })
const onCurrentChange = (page: number) => {
currentPage.value = page
refresh()
}
const onSizeChange = (size: number) => {
pageSize.value = size
currentPage.value = 1 // 切换每页条数通常回到第 1 页
refresh()
}
// 初始化请求
if (options.initFetch !== false) {
search(options.params)
}
return {
currentPage,
pageSize,
total,
data,
isFetching,
search,
refresh,
onCurrentChange,
onSizeChange
}
}
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










