vue 3中axios封装采用“分层解耦”设计:request层负责axios实例配置与拦截器,api层按业务域拆分接口函数并标注ts类型,service层可选增强逻辑;接口路径统一由环境变量控制,api文件通过聚合导出提升导入体验。

Vue 3 中 Axios 封装的模块化 API 组织,核心是“分层解耦”:把请求逻辑(怎么发)和业务接口(发什么)彻底分开。不推荐把所有接口写在一个文件里,也不建议在组件中直接调用 axios —— 这样既难维护,也破坏了关注点分离。
1. 分三层结构:request → api → service
这是目前主流且可长期演进的组织方式:
-
request.ts(或 request.js):仅负责创建 axios 实例、配置 baseURL、超时、拦截器(加 token、错误统一处理、取消重复请求等)。它不关心任何业务路径,只管“怎么发”。导出的是封装好的
service实例。 -
api/ 目录下按业务域拆分文件,例如:
userApi.ts、menuApi.ts、orderApi.ts。每个文件只定义本模块的请求函数,如getUserInfo()、updateUser(data),内部调用service.get()或service.post()。 - service/(可选):更进一步,可将 api 层再包装一层,加入缓存控制、权限校验前置、loading 状态联动等业务增强逻辑。适合中大型项目,小项目可省略,直接在 api 文件里返回 Promise。
2. api 文件写法示例(以 userApi.ts 为例)
每个函数语义清晰、参数明确、返回类型可推断:
import { service } from '@/utils/request'
import type { UserResponse, LoginParams } from '@/types/user'
<p>// 登录(无需 token)
export const login = (data: LoginParams) =>
service.post<userresponse>('/base/access_token', data, { noNeedToken: true })</userresponse></p><p>// 获取当前用户信息(需 token)
export const getUserInfo = () =>
service.get<userresponse>('/base/userinfo')</userresponse></p><p>// 获取用户菜单
export const getUserMenu = () =>
service.get<string>('/base/usermenu')
</string></p>
注意两点:一是使用 TypeScript 泛型标注响应数据类型;二是通过配置项(如 { noNeedToken: true })控制拦截器行为,比硬编码判断更灵活。

