文章目录
前言
axios是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中,可以配合vue、react等框架使用,用于实现网络请求。网上已经有很多与axios封装有关的博客,本文主要阐述在基础封装的思路上,如何配合elementUI和vue完成一个完整实用的,具有自定义功能的axios封装
一、准备工作
- 建议在Vue CLI中使用,所以需要先创建一个脚手架项目(勾选使用vue-router和vuex)
- 安装elementUI
npm i element-ui -S
oryarn add element-ui
- 安装QS库(处理参数)
npm i qs -S
oryarn add qs
- 安装axios
npm i axios -S
oryarn add axios
二、创建js文件
自己寻找一个合适的位置创建文件夹,来专门放置和网络请求相关的文件。我个人选择在src目录下创建一个service文件夹,在service文件夹下创建api.js来封装网络请求,以及后续在service下创建功能接口文件夹。
| |-- src // 源码目录
| | |-- service // 网络请求管理文件夹
| | | |-- api.js // 封装axios请求
三、开始封装
准备工作已经全部完成了,下面让我们快乐地封装axios╮( ̄▽ ̄)╭
1.参数设置
我们首先将我们封装的函数赋予常量取名NetworkRequest并进行导出,这个函数接收options作为参数(options就是我们稍后会传入的配置参数对象)并返回一个Promise:
export const NetworkRequest = options => {
return new Promise((resolve,reject)=>{
})
}
添加上我们需要引入的依赖,这些依赖会在后面用到的时候说明具体作用,同时我们为方法书写一段注释,注释中标明了我们可能传入的具体字段,并在函数中引用:
import Store from '@/store/index';//引入vuex
import router from '@/router';//引入vue-router
import {
Message,MessageBox,Loading} from 'element-ui';//按需引入element中所需的组件
import axios from 'axios';//引入axios
import qs from 'qs';//引入qs
axios.defaults.baseURL = '/api/';//设置默认前置url为/api/,用于反向代理跨域
/**
* @param {Object} options 网络请求用户配置 timeout:超时时间{number}<可选>
* headerType:请求头{String}<可选>
* throttle:是否需要loading节流{Boolean}<可选>
* url:API地址{String}<可选>
* method:请求方式{String}
* data:请求时携带的参数{Object}<可选>
* fileType:是否为需要实时上传进度的文件类型{Boolean}<可选>
* @returns {Promise<Object>}
*/
export const NetworkRequest = options => {
return new Promise((resolve,reject)=>{
let {
timeout,headerType,throttle,url,method,data,fileType} = options;
axios.defaults.timeout = timeout || 30000;//设置请求超时时间
//设置请求头
axios.defaults.headers.post['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
axios.defaults.headers.put['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
axios.defaults.headers.delete['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
})
}
2.设置请求拦截
axios为我们提供了请求拦截的回调函数,请求拦截就是在我们的网络请求正式发出去之前,先拦截以进行一些自定义的处理,一般这个时候我们可以将token信息挂上请求头,或者做下接口的权限验证:
import Store from '@/store/index';//引入vuex
import router from '@/router';//引入vue-router
import {
Message,MessageBox,Loading} from 'element-ui';//按需引入element中所需的组件
import axios from 'axios';//引入axios
import qs from 'qs';//引入qs
axios.defaults.baseURL = '/api/';//设置默认前置url为/api/,用于反向代理跨域
/**
* @param {Object} options 网络请求用户配置 timeout:超时时间{number}<可选>
* headerType:请求头{String}<可选>
* throttle:是否需要loading节流{Boolean}<可选>
* url:API地址{String}<可选>
* method:请求方式{String}
* data:请求时携带的参数{Object}<可选>
* fileType:是否为需要实时上传进度的文件类型{Boolean}<可选>
* @returns {Promise<Object>}
*/
export const NetworkRequest = options => {
return new Promise((resolve,reject)=>{
let loading = null;//全局加载
let {
timeout,headerType,throttle,url,method,data,fileType} = options;
axios.defaults.timeout = timeout || 30000;//设置请求超时时间
//设置请求头
axios.defaults.headers.post['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
axios.defaults.headers.put['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
axios.defaults.headers.delete['Content-Type'] = headerType || 'application/x-www-form-urlencoded';
//请求拦截
axios.interceptors.request.use(config=>{
//如果方法调用者需要全局loading效果,则启用elementUI的Loading效果
if(throttle){
loading = Loading.service({
lock: true,
text: '请稍等',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
}
//这里是将用户登录后的token信息存放在了vuex中,判断一下token是否存在,若存在则在请求头中添加字段'token',向服务端传递用户的token(这里需要服务端配合进行解析)
if(Store.state.userToken!==null){
config.headers['token'] = Store.state.userToken;
}
return config;//结束拦截,继续执行请求
},error=>{
//捕获到了请求超时的错误,调用elementUI的Message弹出提示信息
Message.error({
message: '请求超时,请稍后重试'});
})
})
}
3.设置响应拦截
axios同样为我们提供了响应拦截的回调函数,响应拦截执行时,请求已经发送成功并成功收到了response,这时我们可以根据自己的需要进行一些全局的请求过滤或自定义事件,这个地方的代码比较灵活,写法与服务端之间的约定和具体需求有关,仅供参考:
import Store from '@/store/index';//引入vuex
import router from '@/router';//引入vue-router
import {
Message,MessageBox,Loading} from 'element-ui';//按需引入element中所需的组件
import axios from 'axios';//引入axios
import qs from 'qs';//引入qs
axios.defaults.baseURL =