Vue二次封装axios为插件使用详解
照例先贴上axios的gitHub地址
不管用什么方式获取数据,对于一个项目来说,代码一定要利于维护其次是一定要写的优美,因此加上一层封装是必要的
vuejs2.0已经不再维护vue-resource,vuejs2.0已经使用了axios,这也是为什么我会转到axios的主要原因,废话不多说:
基本的封装要求:
- 统一url配置
- 统一api请求
- request(请求)拦截器,例如:带上token等,设置请求头
- response(响应)拦截器,例如:统一错误处理,页面重定向等
- 根据需要,结合Vuex做全局的loading动画,或者错误处理
- 将axios封装成Vue插件使用
文件结构
使用vue-cli进行相关的封装,在src文件夹下:
src | --http封装axios模块文件夹 | ----config.jsaxios的默认配置 ----api.js二次封装axios,拦截器等 ----interface.js请求接口文件 ----index.js将axios封装成插件
config.js
默认配置参照gitHub,以下只做示例:
exportdefault{ method:'post', //基础url前缀 baseURL:'https://easy-mock.com/mock/5ad75e9f41d4d65f0e935be4/example', //请求头信息 headers:{ 'Content-Type':'application/json;charset=UTF-8' }, //参数 data:{}, //设置超时时间 timeout:10000, //携带凭证 withCredentials:false, //返回数据类型 responseType:'json' }
PS:这里推荐一下一款Mock工具EasyMock,以上请求地址来自该工具。以后有空会单独写一下怎么使用该工具。
api.js
importaxiosfrom'axios'//注意先安装哦 importconfigfrom'./config.js'//倒入默认配置 importqsfrom'qs'//序列化请求数据,视服务端的要求 exportdefaultfunction$axios(options){ returnnewPromise((resolve,reject)=>{ constinstance=axios.create({ baseURL:config.baseURL, headers:{}, transformResponse:[function(data){}] } ) //request拦截器 instance.interceptors.request.use( config=>{ //Tip:1 //请求开始的时候可以结合vuex开启全屏的loading动画 //Tip:2 //带上token,可以结合vuex或者重localStorage //if(store.getters.token){ //config.headers['X-Token']=getToken()//让每个请求携带token--['X-Token']为自定义key请根据实际情况自行修改 //}else{ ////重定向到登录页面 //} //Tip:3 //根据请求方法,序列化传来的参数,根据后端需求是否序列化 if(config.method.toLocaleLowerCase()==='post' ||config.method.toLocaleLowerCase()==='put' ||config.method.toLocaleLowerCase()==='delete'){ config.data=qs.stringify(config.data) } returnconfig }, error=>{ //请求错误时做些事(接口错误、超时等) //Tip:4 //关闭loadding console.log('request:',error) //1.判断请求超时 if(error.code==='ECONNABORTED'&&error.message.indexOf('timeout')!==-1){ console.log('根据你设置的timeout/真的请求超时判断请求现在超时了,你可以在这里加入超时的处理方案') //returnservice.request(originalRequest);//例如再重复请求一次 } //2.需要重定向到错误页面 consterrorInfo=error.response console.log(errorInfo) if(errorInfo){ //error=errorInfo.data//页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.reject consterrorStatus=errorInfo.status;//404403500...等 router.push({ path:`/error/${errorStatus}` }) } returnPromise.reject(error)//在调用的那边可以拿到(catch)你想返回的错误信息 } ) //response拦截器 instance.interceptors.response.use( response=>{ letdata; //IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串) if(response.data==undefined){ data=response.request.responseText }else{ data=response.data } //根据返回的code值来做不同的处理(和后端约定) switch(data.code){ case'': break; default: } //若不是正确的返回code,且已经登录,就抛出错误 //consterr=newError(data.description) //err.data=data //err.response=response //throwerr returndata }, err=>{ if(err&&err.response){ switch(err.response.status){ case400: err.message='请求错误' break case401: err.message='未授权,请登录' break case403: err.message='拒绝访问' break case404: err.message=`请求地址出错:${err.response.config.url}` break case408: err.message='请求超时' break case500: err.message='服务器内部错误' break case501: err.message='服务未实现' break case502: err.message='网关错误' break case503: err.message='服务不可用' break case504: err.message='网关超时' break case505: err.message='HTTP版本不受支持' break default: } } console.error(err) //此处我使用的是elementUI的提示组件 //Message.error(`ERROR:${err}`); returnPromise.reject(err)//返回接口返回的错误信息 } ) //请求处理 instance(options) .then((res)=>{ resolve(res) returnfalse }) .catch((error)=>{ reject(error) }) }) }
interface.js
importaxiosfrom'./api'//倒入api /*将所有接口统一起来便于维护 *如果项目很大可以将url独立成文件,接口分成不同的模块 *此处的数据依然来自EasyMock */ //单独倒出 exportconstquery=params=>{ returnaxios({ url:'/query', method:'get', params }) } exportconstmock=params=>{ returnaxios({ url:'/mock', method:'get', params }) } exportconstupload=data=>{ returnaxios({ url:'/upload', method:'post', data }) } //默认全部倒出 //根绝需要进行 exportdefault{ query, mock, upload }
index.js
封装成Vue插件,便(提)于(高)使(B)用(格)
//倒入所有接口 importapiListfrom'./interface' constinstall=Vue=>{ if(install.installed) return; install.installed=true; Object.defineProperties(Vue.prototype,{ //注意哦,此处挂载在Vue原型的$api对象上 $api:{ get(){ returnapiList } } }) } exportdefaultinstall
使用
到此为止,万事俱备就差用了,在mian.js中做如下操作:
//倒入http文件夹下的index.js importapifrom'./http/index' Vue.use(api) //此时可以直接在Vue原型上调用$api了
总结
- 以上二次封装较为全面,基本完成了我们之前的需求
- 在错误的处理上还需要与后端协定好返回值,做具体的约定
- 封装回调有点多,在使用的时候也需要加上then()来处理结果,async&await了解一下哟,好东西当然要藏起来,我才不会分享出来呢...
PS:IE9不支持Promise哦,需要安装一个polyfill
import'babel-polyfill'
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。