跳到主要内容从接口文档到前端调用:Axios 封装与实战详解 | 极客日志JavaScript大前端
从接口文档到前端调用:Axios 封装与实战详解
介绍如何阅读接口文档区分 GET 与 POST 请求参数,演示 Axios 实例创建及请求/响应拦截器的封装方法(含 Token 注入与错误处理),并提供 GET、POST、DELETE、PUT、PATCH 等常见 HTTP 方法在 Vue 项目中的实际 API 封装与调用示例。
时间旅人1 浏览 从接口文档到前端调用:Axios 封装与实战详解
1. 如何看接口文档?
在一个接口文档中,有很多的请求类型(也叫 HTTP 方法 / 动作)
- GET
- POST
- PUT
- PATCH
- DELETE
这里仅以 GET 和 POST 做讲解,其他的请求类型,都类似
1.1 GET
注意:GET 跟 URL 息息相关
来看一个具体的例子:


首先,接口都会有一个 baseUrl,作为获取数据的地址,使用不同的接口时,又会有不同的路径,比如这个就是 /my/cate/info
第一部分:请求参数(Request Parameters)
Query 参数和 Header 参数
query 跟 url 息息相关
header 跟身份验证相关,就是说,想让这个请求发送给接口,必须满足一些条件,header 就像一把钥匙
文档中这两部分都必须传对,否则接口要么报错,要么不给你数据。
- Query 参数
- 出现在 URL 上。
- 所以:Query 参数就是用来指定查询条件的。
在这个接口里:
GET /my/cate/info?id=1284
这里的 id=1284 就是 文章分类的 id,告诉后台我要取哪一个分类的详情。
- Header 参数
- 放在 HTTP 请求的 请求头里。
- 这里要求的参数是:
Authorization: Bearer <token>
Authorization:英语中授权的意思
- 作用:用来验证用户身份(你是否已经登录)。
- 也就是说:
- 如果没有这个 token → 后台会返回 401 身份认证失败。
- 有正确 token → 才能拿到分类详情。
第二部分:响应(Response)
{"code"
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
:
0
,
"message"
:
"获取文章分类成功!"
,
"data"
:
{
"id"
:
1070
,
"cate_name"
:
"科技"
,
"cate_alias"
:
"keji"
}
}
- code:业务状态码。
- message:提示消息(给人看的,比如'成功/失败原因')。
- data:真正的业务数据,这里是文章分类的详情对象。
id:分类 ID。
cate_name:分类名称(比如'科技')。
cate_alias:分类别名(比如'keji')。
这部分就是告诉你:调用成功以后,后台会返回什么样的数据结构,你前端代码里就可以用这些字段来展示页面。
1.2 POST
看如下例子:返回响应部分不做介绍,POST 请求方法没有 Query 参数,而是 Body 参数
- 位置:请求报文的 body 部分,不在 URL 上。
- 格式:这里文档写了
application/json,说明 body 要用 JSON 格式。
- 作用:用来传递 新增数据的内容。
- cate_name (string)
- 文章分类名字,比如'娱乐'、'科技'。
- 必填,长度限制:1–10 个非空字符。
- cate_alias (string)
- 文章分类别名,比如'yule'、'keji'。
- 必填,长度限制:1–15 个大小写字母和数字组合。
{ "cate_name": "娱乐", "cate_alias": "yule" }
为什么 GET 没有 Body,而 POST 要用 Body?
GET:只是获取数据,不修改,所以参数少,放 URL 上即可。
POST:要创建一条新数据,通常包含多个字段(标题、别名、内容……),如果写在 URL 会很长很乱,所以必须放到 Body 里,结构化成 JSON。
2. 为什么要封装请求拦截器和响应拦截器?如何封装?
简单来说,实际开发过程中,不能每一次都手动的在请求头中加入授权的 token,而请求拦截器,会拦截请求将每个授权的 token 加入到本次的请求头当中。
import axios from 'axios'
const baseURL = 'http://big-event-vue-api-t.itheima.net'
const instance = axios.create({
})
instance.interceptors.request.use((config) => {
return config
}, (err) => Promise.reject(err))
instance.interceptors.response.use(
(res) => {
return res
},
(err) => {
return Promise.reject(err)
}
)
export default instance
- 将封装写在
src/utils/request.js
- 首先,创建一个 axios 实例
- 其次,写出请求拦截器和响应拦截器
2.1 封装 axios 实例
- 每个接口都要用到的公共参数,比如:
baseURL(基础路径)
timeout(超时时间)
headers(请求头,常常要放 token)
- 如果不封装,每次
axios.get() / axios.post() 都要手动写,很麻烦。
- 封装后 → 写一次,所有请求自动带上。
timeout:请求超过 x 毫秒还没响应,就自动报错,进入 .catch()
请求中几乎所有接口都需要,而且不会频繁变化 的东西,适合直接写在 axios.create() 的 headers 里,所以 token 不应该写在这里,token 应写在拦截器中
- 以后如果
baseURL 要改(比如从测试环境 → 正式环境),只需要改 request.js 这一处。
- 如果不封装,你得在项目里到处找 URL,一个个修改,容易遗漏。
- 一部分接口走
https://api.example.com
- 另一部分接口走
https://upload.example.com
就可以创建两个不同的 axios 实例,互不影响。
import axios from 'axios'
const baseURL = 'http://big-event-vue-api-t.itheima.net'
const instance = axios.create({ baseURL, timeout: 100000 })
2.2 封装拦截器
axios.interceptors.request.use(function(config) {
return config;
}, function(error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function(response) {
return response;
}, function(error) {
return Promise.reject(error);
});
request 拦截器的代码是一样的,关键在于拿到的对象不一样,一个是 config,一个是 response
- config 对象
- axios 会先把你传入的参数转成一个'配置对象',这个配置对象就是 config 对象
- response 对象
- 浏览器原生的 XHR 或 fetch 会产生一个响应结果,axios 会把这个结果'包装'成一个对象
- 这里的 axios.替换成你对应的 axios 实例
- function(config) 也可以替换成对应的箭头函数 ()=>{}
2.3 拦截器实践
请求拦截器:使用 pinia 存储的 token,将 token 值赋给请求头
instance.interceptors.request.use((config) => {
const userStore = useUserStore()
if(userStore.token){ config.headers.Authorization = userStore.token }
return config
}, (err) => Promise.reject(err))
- 成功拿到响应,直接返回,没拿到服务异常
- 若错误,根据错误类型提示或跳转路由
instance.interceptors.response.use((res) => {
if(res.data.code === 0){return res}
ElMessage({ message: res.data.message ||'服务异常', type:'error'})
return Promise.reject(res.data)
}, (err) => {
ElMessage({ message: err.response.data.message ||'服务异常', type:'error'})
console.log(err)
if(err.response?.status === 401){ router.push('/login')}
return Promise.reject(err)
})
export default instance
export{ baseURL }
3. 如何在实际的项目中使用 axios
3.1 GET
在 src/api 下创建自定义的 js 文件,如 article.js。存放跟文章相关的 api
import request from '@/utils/request'
export const artGetChannelsService = () => request.get('/my/cate/list')
const res = await artGetChannelsService()
import { artGetChannelsService } from '@/api/article'
export const artGetChannelDetailService = (id) => {
return request.get('/my/cate/info', {
params: { id }
})
}
import { artGetChannelDetailService } from '@/api/article'
const id = route.query.id
await artGetChannelDetailService(id)
3.2 POST
import request from '@/utils/request'
export const artAddChannelService = (data) => request.post('/my/cate/add', data)
使用该方法,此时注意了,POST 是需要我们传参的
const formModel = ref({ cate_name:'', cate_alias:''})
await artAddChannelService(formModel.value)
import { artAddChannelService } from '@/api/article'
3.3. DELETE
Delete 也是需要一个请求参数,写法跟带参数的 GET 一样
export const artDelChannelService = (id) => request.delete('/my/cate/del', {
params: { id }
})
3.4 PUT
put 跟 post 写法一样,除了 request 方法是 put
export const artEditChannelService = (data) => request.put('/my/cate/info', data)
在实际写法中,也可以不用形参 data,直接传对象,比如
export const userUpdateInfoService = ({ id, nickname, email }) => request.put('/my/userinfo', { id, nickname, email })
3.5 PATCH
export const userUploadAvatarService = (avatar) => request.patch('/my/update/avatar', { avatar })