签入版本
This commit is contained in:
@@ -1,62 +1,41 @@
|
||||
# 9.4 HTTP 请求封装
|
||||
|
||||
:::tip 概述
|
||||
前端使用 Axios 封装 HTTP 请求,自动处理 Token 携带、响应码判断、错误提示。
|
||||
`utils/http/axios` 是自研的 axios 封装层:请求拦截(前缀、Token)、响应拦截(信封解包、错误提示、401 处理)、取消重复请求。业务代码只面对"成功拿 data"的干净接口。
|
||||
:::
|
||||
|
||||
## 封装结构
|
||||
## 文件结构
|
||||
|
||||
```text
|
||||
src/utils/http/axios/
|
||||
├── index.ts # Axios 实例配置和拦截器
|
||||
├── Axios.ts # VAxios 类封装
|
||||
├── axiosTransform.ts # 数据转换接口
|
||||
├── checkStatus.ts # HTTP 状态码处理
|
||||
├── helper.ts # 辅助函数
|
||||
└── types.ts # 类型定义
|
||||
utils/http/axios/
|
||||
├── Axios.ts axios 实例创建与拦截器装配
|
||||
├── axiosTransform.ts 转换器基类(各拦截点的抽象)
|
||||
├── index.ts 本项目转换器实现(核心业务逻辑)
|
||||
├── checkStatus.ts HTTP 状态码 → 提示文案映射
|
||||
├── axiosCancel.ts 重复请求取消
|
||||
├── helper.ts 辅助函数
|
||||
└── types.ts 类型定义
|
||||
```
|
||||
|
||||
## 核心拦截器
|
||||
## 拦截流程
|
||||
|
||||
### 请求拦截器(自动携带 Token)
|
||||
|
||||
```typescript
|
||||
// src/utils/http/axios/index.ts
|
||||
|
||||
// 请求前自动添加 Token
|
||||
config.headers['Authorization'] = `Bearer ${token}`;
|
||||
```text
|
||||
请求发出
|
||||
→ 前置:拼接 VITE_GLOB_API_URL_PREFIX + URL,附加 Authorization: Bearer
|
||||
→ 发送(重复请求按策略取消)
|
||||
↓
|
||||
响应返回
|
||||
→ 后置:判断 HTTP 状态 → 解包信封
|
||||
ok=true → 返回 data(业务函数直接拿数据)
|
||||
code=401 → 清令牌跳登录(或触发刷新)
|
||||
其余失败 → 统一 toast msg,抛错给调用方 catch
|
||||
↓
|
||||
业务代码
|
||||
```
|
||||
|
||||
### 响应拦截器(统一错误处理)
|
||||
## 使用形态(摘自 ui/src/api/tool/example.ts)
|
||||
|
||||
```typescript
|
||||
// 响应处理逻辑
|
||||
const { code, data, msg } = res.data;
|
||||
|
||||
if (code === 0) {
|
||||
return data; // 成功,返回 data
|
||||
}
|
||||
|
||||
if (code === 401) {
|
||||
// Token 过期,跳转登录
|
||||
router.push('/login');
|
||||
}
|
||||
|
||||
// 其他错误,显示提示
|
||||
ElMessage.error(msg || '操作失败');
|
||||
```
|
||||
|
||||
:::tip 响应处理规则
|
||||
- `code === 0`:成功,返回 `data`
|
||||
- `code === 401`:Token 过期,自动跳转登录页
|
||||
- `code === 403`:权限不足,显示错误提示
|
||||
- 其它 `code`:业务失败,显示 `msg`
|
||||
:::
|
||||
|
||||
## API 模块编写
|
||||
|
||||
```typescript
|
||||
// src/api/tool/example.ts
|
||||
import { http } from '@/utils/http/axios';
|
||||
|
||||
export function getExamplePage(params?: Record<string, any>) {
|
||||
@@ -66,25 +45,23 @@ export function getExamplePage(params?: Record<string, any>) {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function exampleAdd(data: any) {
|
||||
return http.request({
|
||||
url: '/example/add',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## 在组件中使用
|
||||
注意 URL **不带 /api 前缀**(由配置统一拼接);Token 与信封判断都不在业务层出现。
|
||||
|
||||
```typescript
|
||||
import { getExamplePage, exampleAdd } from '@/api/tool/example';
|
||||
## 错误处理约定
|
||||
|
||||
// 获取列表
|
||||
const res = await getExamplePage({ pageNo: 1, pageSize: 10 });
|
||||
tableData.value = res.records;
|
||||
| 层 | 行为 |
|
||||
|---|---|
|
||||
| 拦截器 | 统一 toast + 401 跳转;返回 reject |
|
||||
| api 模块 | 不 catch(透传) |
|
||||
| 页面 | 需要特殊处理才 catch(如表单保留输入),否则由拦截器兜底提示 |
|
||||
|
||||
// 新增
|
||||
await exampleAdd({ name: '测试', status: 1 });
|
||||
```
|
||||
## 类型支持
|
||||
|
||||
`http.request<T>()` 支持泛型标注返回 data 类型,逐步为 api 模块补类型是推荐实践。
|
||||
|
||||
## 相关
|
||||
|
||||
- [8.1 统一响应格式](/zh/api-spec/response.html)(信封契约)
|
||||
- [9.14 API 模块编写规范](/zh/frontend/api-module.html)
|
||||
|
||||
Reference in New Issue
Block a user