Pinia Actions 处理分页列表的核心是统一管理请求参数、状态生命周期和数据累加逻辑;state 显式声明 list、pagination、loading、error 字段;actions 封装 fetchList 支持首次加载、追加加载、跳转指定页;可选集成 AbortController 防竞态。

Pinia Actions 处理分页列表数据的异步加载,核心是把“请求参数管理 + 状态生命周期控制 + 数据累加逻辑”三者统一收口在 Action 内,避免组件中手动拼接页码、维护 loading、处理翻页时的数据覆盖或竞态问题。
定义清晰的分页状态字段
在 store 的 state 中显式声明分页相关响应式字段,不只是 data 和 loading:
- list:当前已加载的所有条目(数组),用于滚动加载或分页切换时保留历史数据
-
pagination:对象结构,包含
currentPage、pageSize、total、hasMore等 - loading:区分全局 loading(如首次进入)和局部 loading(如“正在加载下一页”)
- error:错误提示,支持清空重试
封装带分页参数的异步 Action
用一个主 Action 统一处理「拉取某页」逻辑,支持两种调用方式:
- 首次加载:传
{ page: 1 },清空 list 并重置分页元信息 - 加载下一页:传
{ append: true },自动递增currentPage,追加数据到 list
示例代码片段:
async fetchList(params = {}) {
const { page = this.pagination.currentPage + 1, append = false } = params;
if (!append) {
this.list = [];
this.pagination = { currentPage: 0, pageSize: 10, total: 0, hasMore: true };
}
this.loading = true;
try {
const res = await api.getList({ page, size: this.pagination.pageSize });
const { list, pagination } = res.data;
if (append) {
this.list.push(...list);
} else {
this.list = list;
}
this.pagination = { ...this.pagination, ...pagination };
} catch (err) {
this.error = err.response?.data?.message || '获取列表失败';
} finally {
this.loading = false;
}
}
组件中按需调用,保持语义明确
组件不直接操作页码或数组拼接,只调用语义化方法:
- 初始化:调用
store.fetchList()(默认从第 1 页开始) - 下拉加载更多:调用
store.fetchList({ append: true }) - 跳转指定页:调用
store.fetchList({ page: 5 })(适合页码输入框)
这样组件只需关注“用户想做什么”,不用关心“当前是第几页”或“要不要清空旧数据”。
可选:加入防抖与请求取消机制
对高频触发场景(如搜索+分页联动),可在 Action 内部集成 AbortController,每次新请求自动中止上一次未完成的请求:
- 在 state 中保存 controller 实例(
controller = null) - 发起请求前调用
this.controller?.abort(),再新建 controller 并传入 fetch - 确保 finally 中清理 controller 引用,防止内存泄漏
这对避免“快速翻页导致后发请求先返回、覆盖正确数据”的竞态问题非常有效。










