我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情
axios文档地址
本文只是对axios进行简单的一些封装和配置,具体的一些细节请移步axios的文档查询!
下面我们就开始进行我们的封装!
最终实现效果
- 在app.js中配置接口(或者可将api.js根据业务进行更细致的划分,后用esm引入拼装)
//api.js
import qs from 'qs'
import base from './base.js'
import serve from './serve.js'
export default {
// post表单请求
getData1(params) {
return server.post(`${base.serve1}/xxxx`, qs.stringify(params))
},
// post json请求
getData2(params) {
return server.post(`${base.serve2}/xxxx`, params)
},
// get 请求
getData2(params) {
return server.get(`${base.serve3}/xxxx`, { params })
},
}
- 在页面中使用
//index.vue
// vue2
methods:{
async getData(){
this.loading = true
const res = await this.$api.getData1(this.data)
this.loading = false
if(res){
// todo
}
}
}
// index.vue
// vue3
import { getData1 } from './api.js'
async setup(){
const { proxy } = getCurrentInstance()
const res = await getData1()
if(res){
// todo
}
}
axios对象的创建
创建 axios
对象,添加基本配置
// serve.js
import axios from 'axios'
const config = {
timeout: 150000
}
const serve = axios.create(config)
这里不对 config.baseUrl
做配置,是因为有些具体的业务可能会调用不同的服务接口,为了更好的维护不同的服务接口,我们在 base.js
文件中做更细致的配置。
创建 base.js
地址文件
// base.js
const base = {}
// 这里可用在配置文件中修改环境变量
const env = process.env.NODE_ENV
switch(env){
case 'development':
base.serve1 = '/development-api1'
base.serve2 = '/development-api2'
break
case 'text':
base.serve1 = '/text-api1'
base.serve2 = '/text-api2'
break
case 'production':
base.serve1 = '/production-api1'
base.serve2 = '/production-api2'
break
}
export default base
在这里不把 url地址
写到配置文件中,是为了在开发时方便切换不同的地址
当 url地址
写在配置文件中,如果需要切换 url地址
,那么修改配置文件之后就需要重启服务,url才会生效
当有些业务要跟A同事联调,有些业务要跟B同事联调的时候,频繁重启服务就会浪费大量的时间
axios拦截器配置
关于拦截器, axios
的官方文档是这么描述的
You can intercept requests or responses before they are handled by
then
orcatch
.
意思就是,拦截器可以让我们在 then
或者 catch
处理之前,执行相关的一些拦截操作
拦截器具体分两种类型:
- 请求拦截
axios.interceptors.request
- 响应拦截
axios.interceptors.response
以下是官方文档的使用demo
// serve.js
// 添加一个请求拦截器
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)
})
请求拦截
HTTP是一个无状态的协议,所以我们在与后端进行数据交互时,会添加一个token字段(或者其他身份标识的字段)来进行数据校验
此时我们就可以在请求拦截的时候,为http请求添加token
// serve.js
import message from 'ui/message'
// 请求拦截,serve是axios创建的实例
serve.interceptors.request.use(
config => {
// 每次请求携带token
const token = getToken()
config.headers.Authorization = token
return config
},
error => message(error)
)
在请求拦截添加token之后,我们所有通过 serve
发送的 http
请求都会携带token
这里有的后端会习惯把token放在请求体里,我们也可用在请求拦截里进行处理
config.data
就是我们发送的数据,可以判断 config.data
的数据类型
根据不同的数据类型为config.data
添加token
响应拦截
在和后端进行数据通信是,一般接口都会约定一个通用的返回结构体以及通用的状态码
这个时候我们就可以在响应拦截里进行通用的代码处理
// serve.js
import { loginOut } from './utils'
// 响应拦截器
serve.interceptors.response.use(
response => {
/** 假设通用结构体如下
{
code:'1001',
msg:'success',
data:{
// 返回的数据
}
} **/
if(response.data.code === '1001') return response
// 假设登录超时的code是 400
if(response.data.code === '400'){
// 做退出登录处理
loginOut()
}
// 如果响应失败,不返回任何数据
},
error => message(error)
)
以上就是 serve.js
文件中的基本处理,以下是 serve.js
文件的完整版
// serve.js
import { loginOut } from './utils'
import axios from 'axios'
const config = {
timeout: 150000
}
const serve = axios.create(config)
// 请求拦截器
serve.interceptors.request.use(
config => {
// 每次请求携带token
const token = getToken()
config.headers.Authorization = token
return config
},
error => message(error)
)
// 响应拦截器
serve.interceptors.response.use(
response => {
/** 假设通用结构体如下
{
code:'1001',
msg:'success',
data:{
// 返回的数据
}
} **/
if(response.data.code === '1001') return response
// 假设登录超时的code是 400
if(response.data.code === '400'){
// 做退出登录处理
loginOut()
}
// 如果响应失败,不返回任何数据
},
error => message(error)
)
export default serve
接口添加配置
上文我们完整地配置了 axios
的实例对象,接下来我们利用这个实例对象来添加我们要联调的接口
// api.js
import qs from 'qs'
import base from './base.js'
import serve from './serve.js'
export default {
// post表单请求
getData1(params) {
return server.post(`${base.serve1}/xxxx`, qs.stringify(params))
},
// post json请求
getData2(params) {
return server.post(`${base.serve2}/xxxx`, params)
},
// get 请求
getData2(params) {
return server.get(`${base.serve3}/xxxx`, { params })
},
// 继续添加你的接口
// todo
}
这里的 api.js
文件就是我们接口总的配置文件,或者你也可以根据业务模块来把api.js进行拆分
最后在 api.js
文件中汇总暴露出去即可,如下
// api.js
import orderApi from './orderApi.js'
import userApi from './userApi.js'
export default {
...orderApi,
...userApi
}
全局挂载
在这里我们为了达到 this.$api.xxx
的使用效果,我们可用将 api.js
文件暴露出来的对象
挂载到vue实例上,这样就可以直接使用
// vue2
// main.js
import Vue from 'vue'
import api from './api.js'
Vue.prototype.$api = api
注意:以上方式只适用于vue2的开发,在 vue3
的 setup
中已经没有 this
,如果一定要在 setup
中通过原型链去访问 $api
, vue内部有一个方法可以获取实例,然后通过实例挂载 $api
// main.js
import { createApp } from 'vue'
import api from './api.js'
const app = createApp(App)
app.config.globalProperties.$api = api
以下是在vue文件中使用(不推荐)
// order.vue
import { getCurrentInstance } from 'vue'
async setup(){
const { proxy } = getCurrentInstance()
const res = await proxy.$api.xxx()
if(res){
// todo
}
}
getCurrentInstance方法是vue内部的api,在vue的文档是没有标注的,如果要在 vue3
中更加规范地编码,可用把 api.js
这个文件进行修改
// api.js
export const getData1 = (params) => {
return server.post(`${base.serve1}/xxxx`, qs.stringify(params))
},
export const getData2 = (params) => {
return server.post(`${base.serve2}/xxxx`, params)
},
export const getData2 = (params) => {
return server.get(`${base.serve3}/xxxx`, { params })
},
修改完后我们在vue文件中使用
// order.vue
import { getData1 } from './api.js'
async setup(){
const { proxy } = getCurrentInstance()
const res = await getData1()
if(res){
// todo
}
}
结语
以上就是对 axios
进行简单封装的全过程,axios
的文档还提供了很多可配置的选项,比如覆盖默认配置、接口取消等等,这里就不展开描述,有需求的可以移步官方文档进行参考和配置。