从接口文档到前端调用:Axios 封装与实战全流程详解
文章目录
从接口文档到前端调用:Axios 封装与实战全流程详解
1.如何看接口文档?
在一个接口文档中,有很多的请求类型(也叫 HTTP 方法 / 动作)
- GET
- POST
- PUT
- PATCH
- DELETE
这里仅以 GET 和 POST 做讲解,其他的请求类型,都类似
1.1 GET
注意:GET 跟 URL 息息相关
来看一个具体的例子:


首先,接口都会有一个 baseUrl,作为获取数据的地址,使用不同的接口时,又会有不同的路径,比如这个就是/my/cate/info
第一部分:请求参数(Request Parameters)
Query 参数和 Header 参数
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":0,"message":"获取文章分类成功!","data":{"id":1070,"cate_name":"科技","cate_alias":"keji"}}- code:业务状态码。
0表示成功,1表示异常。
- message:提示消息(给人看的,比如“成功/失败原因”)。
- data:真正的业务数据,这里是文章分类的详情对象。
id:分类 ID。cate_name:分类名称(比如 “科技”)。cate_alias:分类别名(比如 “keji”)。
这部分就是告诉你:调用成功以后,后台会返回什么样的数据结构,你前端代码里就可以用这些字段来展示页面。
1.2 POST
看如下例子:返回响应部分不做介绍,POST 请求方法没有 Query 参数,而是 Body 参数


Body 参数(请求体)
这是 POST 接口的重点,和 GET 很不同:
- 位置:请求报文的 body 部分,不在 URL 上。
- 格式:这里文档写了
application/json,说明 body 要用 JSON 格式。 - 作用:用来传递 新增数据的内容。
在文档里,它定义了两个字段:
- cate_name (string)
- 文章分类名字,比如“娱乐”、“科技”。
- 必填,长度限制:1–10 个非空字符。
- cate_alias (string)
- 文章分类别名,比如“yule”、“keji”。
- 必填,长度限制:1–15 个大小写字母和数字组合。
示例 JSON:
{ "cate_name": "娱乐", "cate_alias": "yule" } 为什么 GET 没有 Body,而 POST 要用 Body?
GET:只是获取数据,不修改,所以参数少,放 URL 上即可。
POST:要创建一条新数据,通常包含多个字段(标题、别名、内容……),如果写在 URL 会很长很乱,所以必须放到 Body 里,结构化成 JSON。
2.为什么要封装请求拦截器和响应拦截器?如何封装?
简单来说,实际开发过程中,不能每一次都手动的在请求头中加入授权的 token,而请求拦截器,会拦截请求将每个授权的 token 加入到本次的请求头当中.
统一封装 axios 请求模板:
官方文档:https://www.axios-http.cn/docs/interceptors
import axios from'axios'const baseURL ='http://big-event-vue-api-t.itheima.net'const instance = axios.create({// 1. 基础地址,超时时间(配置项)})//请求拦截器 instance.interceptors.request.use((config)=>{// 2. 携带token,将 token 值赋给请求头return config },(err)=> Promise.reject(err))//响应拦截器 instance.interceptors.response.use(//http 返回 200 成功(res)=>{// 3. 正确拿到了业务数据// 4. 业务逻辑错误,例如限制密码字母大写return res },(err)=>{// 5. 处理http 返回401错误return Promise.reject(err)})exportdefault instance - 将封装写在
src/utils/request.js - 首先,创建一个 axios 实例
- 其次,写出请求拦截器和响应拦截器
2.1 封装axios实例
(1)统一配置
- 每个接口都要用到的公共参数,比如:
baseURL(基础路径)timeout(超时时间)headers(请求头,常常要放 token)
- 如果不封装,每次
axios.get()/axios.post()都要手动写,很麻烦。 - 封装后 → 写一次,所有请求自动带上。
timeout:请求超过 x 毫秒还没响应,就自动报错,进入.catch()
请求中几乎所有接口都需要,而且不会频繁变化 的东西,适合直接写在axios.create()的headers里,所以 token 不应该写在这里,token 应写在拦截器中
(2)更好的可维护性
- 以后如果
baseURL要改(比如从测试环境 → 正式环境),只需要改request.js这一处。 - 如果不封装,你得在项目里到处找 URL,一个个修改,容易遗漏。
(3)添加请求/响应拦截器
(4)支持多实例
有些项目里:
- 一部分接口走
https://api.example.com - 另一部分接口走
https://upload.example.com
就可以创建两个不同的 axios 实例,互不影响。
封装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){// 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么return response;},function(error){// 超出 2xx 范围的状态码都会触发该函数。// 对响应错误做点什么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)})导出
exportdefault instance export{ baseURL }3.如何在实际的项目中使用axios
3.1 GET
无需请求参数的 GET

在 src/api 下创建自定义的 js 文件,如 article.js.存放跟文章相关的 api
src/api/article.js
- 导入封装好的方法
import request from'@/utils/request'- 实现 api
//获取文章分类exportconstartGetChannelsService=()=>request.get('/my/cate/list')- 在具体的.vue 文件中使用
使用该方法
const res =awaitartGetChannelsService()导入该方法
import{ artGetChannelsService}from'@/api/article'需要请求参数的 GET

API 封装:
// 获取文章分类详情 ?id=xxxexportconstartGetChannelDetailService=(id)=>{return request.get('/my/cate/info',{ params:{ id }// => /my/cate/info?id=1284})}为什么写 params 呢?
因为能拼到 url 后面
在 .vue 里使用:
import{ artGetChannelDetailService }from'@/api/article'const id = route.query.id // 比如路由里带着 ?id=1284awaitartGetChannelDetailService(id)3.2 POST
以这个为例:

- 导入封装好的方法
import request from'@/utils/request'- 实现 api
//添加文章分类exportconstartAddChannelService=(data)=>request.post('/my/cate/add',data)- 在具体的.vue 文件中使用
使用该方法,此时注意了,POST 是需要我们传参的
//定义表单数据const formModel=ref({ cate_name:'', cate_alias:''})awaitartAddChannelService(formModel.value)导入该方法
import{ artAddChannelService}from'@/api/article'3.3. DELETE
Delete 也是需要一个请求参数,写法跟带参数的 GET 一样
API 封装:
// 删除文章分类exportconstartDelChannelService=(id)=> request.delete('/my/cate/del',{ params:{ id }})3.4 PUT
put 跟 post 写法一样,除了 request 方法是 put
API 封装:
exportconstartEditChannelService=(data)=> request.put('/my/cate/info',data)在实际写法中,也可以不用形参 data,直接传对象,比如
//更新个人信息exportconstuserUpdateInfoService=({ id, nickname, email })=> request.put('/my/userinfo',{ id, nickname, email })3.5 PATCH

API 封装:
跟 post 一样
//上传头像exportconstuserUploadAvatarService=(avatar)=> request.patch('/my/update/avatar',{ avatar })