vue 3 中 axios 封装结合 pinia 管理全局请求加载状态,核心是将 loading 控制权移交 store 并通过拦截器联动生命周期;采用计数器式 loading 对象(如 loading: { user: 0, order: 0 })支持并发与粒度控制,配合 start(key)/finish(key) 方法和 isanyloading 计算属性,在请求拦截器中按白名单开启、响应拦截器中无论成败均关闭,组件仅订阅 store 状态,错误提示与 loading 完全解耦。

Vue 3 中 Axios 封装结合 Pinia 管理全局请求加载状态,关键在于把 loading 控制权从组件移交给 store,再通过拦截器联动请求生命周期。不是简单开关一个布尔值,而是要应对并发、白名单、粒度控制等真实场景。
定义 Loading Store:支持并发与粒度控制
在 Pinia store 中声明 loading 状态,不只用 isLoading: boolean,而推荐使用对象结构或计数器,避免多个请求互相覆盖:
- 基础方案(适合轻量项目):
isLoading: boolean,配合请求池计数(+1 请求,−1 响应) - 进阶方案(推荐):
loading: { user: 0, order: 0, list: 0 },按接口标识统计请求数,值 > 0 即为加载中 - 提供统一方法:
start(key)和finish(key),自动增减并同步更新全局isAnyLoading计算属性
在 Axios 拦截器中联动 store
请求拦截器负责“开启”,响应拦截器(含 error)负责“关闭”,且必须保证执行——用 try/finally 或拦截器的 fulfilled/rejected 双通道:
- 请求前:检查是否在白名单(如登录、上传等无需 loading 的接口),不在则调用
store.start(config.url || 'default') - 响应后:无论成功失败,都执行
store.finish(config.url || 'default');避免因网络中断、超时未进入响应拦截器导致 loading 残留 - 注意:不要在拦截器里直接改
store.isLoading = false,而应调用封装好的 action,保持逻辑集中
组件中响应式绑定 loading 状态
组件不再维护自己的 isLoading,而是直接订阅 store 的计算状态:
- 全局 loading(如顶部进度条、全屏遮罩):绑定
store.isAnyLoading - 局部 loading(如按钮、列表):绑定
store.loading.user > 0或store.loading['/api/order/list'] > 0 - 搭配 UI 库更顺滑:Ant Design Vue 用
<a-spin :spinning="store.isAnyLoading"></a-spin>,Element Plus 用<el-loading :v-loading="store.isAnyLoading"></el-loading>
补充:错误提示与 loading 解耦
loading 状态和错误提示不应强耦合。建议:
- loading 仅反映“是否有请求正在进行”,由拦截器全自动控制
- 错误提示单独处理:在响应拦截器中判断
response.data.code !== 200或error.response?.status,调用message.error(),不干扰 loading 流程 - 这样即使某个请求失败但其他还在跑,loading 仍保持开启,体验更真实
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










