Pinia 实现页面加载 Loading 状态统一管理的关键是将控制逻辑抽离至 store actions 中,通过对象化 loading 状态、computed 派生全局状态、action 内自动开关、组件只读消费及进阶防重提交与超时处理等机制,确保状态集中、一致、可靠。

Pinia 实现页面加载 Loading 状态的统一管理,关键是把 loading 控制逻辑从组件中抽离出来,集中到 store 的 actions 里,让所有异步请求都经过同一套开关机制,避免重复声明、状态不一致或遗漏重置。
定义可复用的 loading 状态结构
在 Pinia store 中,推荐用对象形式管理 loading,支持多请求并行控制:
- 基础写法:loading: { login: false, fetchList: false, submitForm: false },每个 key 对应一个业务动作
- 配合 computed 派生全局状态,例如:isAnyLoading: computed(() => Object.values(this.loading).some(Boolean)),用于控制全屏遮罩
- 若只需简单全局 loading,也可用布尔值 isLoading: boolean,但粒度较粗,不利于并发请求区分
在 action 中自动开关 loading
所有接口调用必须封装进 store 的 action,内部统一处理 loading 生命周期:
- 进入 action 时,根据传入的 key(如 'fetchList')设为 true
- 用 try / finally 或 Promise.finally() 确保无论成功失败都重置对应 key
- 示例:this.loading.fetchList = true; try { await api.getList(); } finally { this.loading.fetchList = false; }
组件中只读取、不干预 loading 状态
组件只负责消费状态,不负责维护或触发:
- 按钮禁用::disabled="userStore.loading.login"
- 全局遮罩:v-if="mainStore.isAnyLoading"
- 表格加载:v-loading="listStore.loading.fetchList"(Element Plus)或自定义骨架屏切换
- 不再需要在 setup 里定义 const loading = ref(false),也不需 emit loading 事件
进阶:增强可靠性与体验
可在 action 层叠加健壮性策略:
- 防重复提交:执行前判断 if (this.loading[key]) return
- 请求超时:启动定时器,10 秒未结束则自动关闭并提示“请求超时”
- 结合 AbortController,在 loading 设为 true 时创建 signal,便于手动中断
- 通过插件方式自动注入 loading(如 store.$loading),对已有 action 零侵入增强


















