如图,面对一堆乱七八糟的代码,你真想说什么F~U~C~K!
回到主题,我们要讲的axios的打包和api接口的统一管理,主要是为了帮助我们简化代码,方便后期的更新和维护。
1.axios封装在vue项目中,与后台交互获取数据。我们通常使用axios库,这是一个基于promise的http库,可以在browser和node.js中运行.它有很多优秀的特性,比如拦截请求和响应、取消请求、转换json、客户端防御XSRF等等。因此,我们公司果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果你还不了解axios,可以浏览一下axios文档。
装置
npm安装axios//安装axios导入
一般来说,我会在项目的src目录中创建新的请求文件夹,然后在其中创建一个新的http.js和api.js文件。Http.js文件用来封装我们的axios,api.js用来统一管理我们的接口。
//从http.js中的' axios '引入axiosimport axios//从“QS”中介绍axios import QS;//引入qs模块序列化post类型的数据,后面会提到vant的toast提示框组件。您可以根据自己的ui组件进行更改。从“vant”导入{ Toast };环境转换
我们的项目环境可能包括开发环境、测试环境和生产环境。我们使用节点的环境变量来匹配默认的接口url前缀。Axios.defaults.baseURL可以设置Axios的默认请求地址。
//环境切换if(process . env . node _ env==' development '){ axios . defaults . base URL=' https://www . Baidu.com ';} else if(process . ENV . NODE _ ENV==' debug '){ axios . defaults . BaseURl=' https://www . ceshi.com ';} else if(process . ENV . NODE _ ENV==' production '){ axios . defaults . BaseURl=' https://www . production.com ';}设置请求超时
通过axios.defaults.timeout设置默认请求超时.比如超过10s,会通知用户当前请求已经超时,请刷新等。
axios . defaults . time out=10000;在设置post请求头时,我们需要添加一个请求头,所以我们可以在这里做一个默认设置,即把post的请求头设置为application/x-www-form-URL encoded;字符集=UTF-8
axios . defaults . headers . post[' Content-Type ']=' application/x-www-form-URL encoded;charset=UTF-8 ';请求拦截我们可以在发送请求之前拦截它。为什么要拦截它?我们在做什么来拦截请求?例如,有些请求只能在用户登录后才能访问,或者我们需要序列化我们在发布请求期间提交的数据。这时,我们可以在请求发送之前对其进行拦截,从而执行我们想要的操作。
请求拦截
//首先导入vuex,因为我们需要使用里面的state对象。//根据vuex的路径从“@/store/index”写入导入存储;//请求拦截器axios . interceptors . request . use(config={//发送请求前,判断令牌是否存在于vuex//中,如果存在,则在http请求的头部添加令牌,后台可以根据令牌判断你的登录状态。//即使令牌在本地存在,也有可能令牌已经过期,所以需要在响应拦截器中判断返回状态。const token=store . state . token;令牌(config.headers.Authorization=令牌);返回配置;},错误={ return Promise.error(错误);})这里就说说token吧。一般登录完成后,用户的令牌通过localStorage或cookie存储在本地,然后每次用户进入页面(即在main.js中)都会先从本地存储中读取令牌。如果令牌存在,vuex中的令牌状态将被更新。然后每次请求一个接口,请求的头部都会携带一个令牌,后台工作人员可以根据你携带的令牌来判断你的登录是否过期。如果没有携带,则表示您没有登录。这时候可能有些朋友会有疑惑,就是每个请求都携带令牌,那么如果一个页面不需要用户登录就可以访问呢?其实你的前端请求可以携带令牌,但是后台可以选择不接收!
响应的截取
//response interceptor axios . interceptors . response . use(response={//如果返回的状态码为200,则表示接口请求成功,可以正常获取数据//否则抛出错误if(response . status==200){ return promise . resolve(response);} else { return Promise.reject(响应);}},//当服务器状态码不以2//开头时,在这里可以和你的后台开发者协商一个统一的错误状态码//然后根据返回的状态码进行一些操作,比如登录到期提示、错误提示等。//下面是一些常见的操作。其他需求可以自己扩展:error={if (error。response.status) {switch(错误。response.status) {//401:如果你没有登录,跳转到登录页面,并携带当前页面的路径。//成功登录后返回当前页面。这一步需要在登录页面进行操作。case 401: router . replace({ path : '/log in ',query : { redirect : router . current out . full path } });打破;//403令牌过期//登录过期时提示用户//清除vuex中的本地令牌和空令牌对象//跳转到登录页面案例40: toast ({message: '登录过期,请重新登录',时长3360 1000,禁止点击3360 true });//清除令牌本地存储。remove item(' token ');store.commit('loginSuccess ',null);//跳转到登录页面,传递要浏览页面的完整路径。成功登录后,跳转到要访问的页面。SetTimeout(()={ router . replace({ path : '/log in ',query : { redirect 3360 router . current out . full path } });}, 1000);打破;//404案例404:吐司在请求中不存在({消息:‘网络请求不存在’,时长: 1500,禁止点击: true });打破;//其他错误,直接抛出错误提示默认: toast ({message : error。response.data.message,持续时间3360 1500,禁止点击: true });}返回Promise . reject(error . response);} } });响应拦截器很容易理解,也就是说,服务器返回的数据可以在我们得到之前进行处理。比如上面的思想:如果后台返回的状态码是200,则数据正常返回;否则,将根据错误的状态代码类型产生一些错误。其实这主要是统一处理错误,在没有登录或者登录过期后调整登录页面的操作。
需要注意的是,上面的Toast()方法是我介绍的vant库中的toast light提示组件,您可以根据自己的ui库使用其中一个提示组件。
封装获取方法和发布方法
我们常用的ajax请求方法包括get、post、put等。我相信我们的朋友会熟悉它们。Axios也有很多类似的方法。如果你不清楚,你可以看看文件。但是为了简化我们的代码,我们仍然需要简单地封装它。这里我们主要封装了两种方法:get和post。
Get方法:我们定义一个get函数,它有两个参数,第一个参数表示我们要请求的url地址,第二个参数是我们要携带的请求参数。get函数返回一个promise对象。当axios的请求成功时,解析服务器返回该值,当请求失败时,拒绝错误值。最后,通过导出抛出get函数。
/** * get方法,对应于get请求* @ param { String } url[请求的URL地址]* @ param { Object } params[请求期间携带的参数] */export函数get(url,params){返回新的Promise((解析,拒绝)={ axios.get(url,{ params:)。然后(RES={ resolve(RES . data);}).catch(err={ reject(err . data)})};}post方法:原理与get基本相同,但需要注意的是,post方法必须使用从parameter对象序列化提交的操作,所以这里我们通过node的qs模块来序列化我们的参数。这一点很重要,如果没有序列化操作,后台就无法得到你提交的数据。这是文章的开头,我们从‘QS’导入QS;原因。如果你不明白序列化是什么意思,就看看百度吧。答案很多。
/** * post方法,对应post请求* @ param { String } url[请求的URL地址]* @ param { Object } params[请求期间携带的参数] */export函数post(url,params) {返回新的Promise((resolve,reject)={ axios.post(url,QS.stringify(params))。然后(RES={ resolve(RES . data);}) .catch(err={ reject(err . data)})};}这里有一个小细节,但是axios.get()方法和axios.post()在提交数据的时候还是有区别的。不同的是get的第二个参数是一个{},那么这个对象的params属性值就是一个参数对象的params属性值。post的第二个参数是一个参数对象。注意两者的细微差别!
axios的封装基本完成。简单说一下api的统一管理。
一个整洁的api就像一个电路板。即使很复杂,也能清楚地理解整个电路。如上所述,我们将创建一个新的api.js,然后将我们所有的api接口存储在这个文件中。
首先,我们将封装的get和post方法引入api.js
/* * * API接口的统一管理*/导入{get,post} from '。例如,现在我们有这样一个接口,它是一个post请求:
http://www.baiodu.com/API/v1/users/my _ address/address _ edit _之前,我们可以将其封装在api.js中,如下所示:
export const APi address=p=post(' API/v1/users/my _ address/address _ edit _ before ',p);我们定义了一个apiAddress方法,它有一个参数p,这是我们请求接口时携带的参数对象。然后我们调用我们封装的post方法。post方法的第一个参数是我们的接口地址,第二个参数是apiAddress的p参数,是请求接口时携带的参数对象。最后,通过导出的方式导出一个地址。
然后我们可以这样调用页面中的api接口:
从“@/request/api”导入{ APi address };//导入我们的api接口export default { name : ' address ',created(){ this . onload();},methods : {//get data OnLoad(){//调用api接口,并提供两个参数apiaddress ({type: 0,sort: 1})。然后(RES={//数据采集成功后的其他操作...})}}其他api接口友好提醒,为每个接口写笔记!api接口管理的一个优点是我们集中了API。如果以后需要修改接口,我们可以直接在api.js中找到对应的修改,而不是去每一个页面找到我们的接口,然后再修改。关键是,如果修改量比较大,就达到了gg规格。还有,如果直接在我们的业务代码中修改接口,很容易不小心触碰到我们的业务代码,造成不必要的麻烦。
好了,最后,完整的axios包代码就呈现出来了。
/**axios封装* 请求拦截、相应拦截、错误统一处理*/从“axios”导入axios从“QS”导入QS;从“万特”导入{ Toast };从""导入存储./store/index'//环境的切换if(过程。ENV。NODE _ ENV==' development '){ axios。默认值。baseURl=“/API”;} else if(process。ENV。NODE _ ENV==' debug '){ axios。默认值。BaseURl=} else if(process。ENV。node _ ENV==' production '){ axios。默认值。基本网址='http://api.123dailu.com/';}//请求超时时间axios。默认值。超时=10000;//帖子请求头axios。默认值。标题。post[' Content-Type ']=' application/x-www-form-URL编码;charset=UTF-8 ';//请求拦截器axios。拦截器。请求。使用(配置={//每次发送请求之前判断是否存在令牌,如果存在,则统一在超文本传送协议(超文本传输协议的缩写)请求的页眉都加上令牌,不用每次请求都手动添加了//即使本地存在令牌,也有可能代币是过期的,所以在响应拦截器中要对返回状态进行判断const令牌=存储。国家。令牌;令牌(配置标题.授权=令牌);返回配置;},错误={返回Promise.error(错误);})//响应拦截器axios。拦截。回应。使用(response={ if(response。状态===200){返回Promise。解决(回应);} else { return Promise.reject(响应);} }, //服务器状态码不是200的情况错误={ if(错误。回应。状态){开关(错误。回应。状态){//401:未登录//未登录则跳转登录页面,并携带当前页面的路径//在登录成功后返回当前页面,这一步需要在登录页操作案例401:路由器。替换({路径: '/登录',查询: {重定向:路由器。电流输出。完整路径} });打破;//403令牌过期//登录过期对用户进行提示//清除本地代币和清空状态管理中代币对象//跳转登录页面案例403: Toast({ message: '登录过期,请重新登录,duration: 1000,forbiddclick : true });//清除令牌localStorage.removeItem('令牌');store.commit('loginSuccess ',null);//跳转登录页面,并将要浏览的页面完整路径传过去,登录成功后跳转需要访问的页面setTimeout(()={ router。替换({路径: '/登录',查询: {重定向:路由器。电流输出。完整路径} });}, 1000);打破;//404请求不存在案例404: Toast({ message: '网络请求不存在,duration: 1500,forbiddclick : true });打破;//其他错误,直接抛出错误提示默认: Toast({消息:错误。回应。数据。消息,持续时间: 1500,禁止点击: true });}返回答应我。拒绝(错误。回应);} });/** *获取方法,对应得到请求* @param {String} url [请求的全球资源定位器(统一资源定位符)地址] * @param {Object}参数[请求时携带的参数]*/导出函数get(url,参数){ 0返回新的承诺(解析,拒绝)={ axios.get(url,{ params: params }).然后(RES={ resolve(RES . data);}) .catch(err={ reject(err。数据)})};}/** *帖子方法,对应邮政请求* @param {String} url [请求的全球资源定位器(统一资源定位符)地址] * @param {Object}参数[请求时携带的参数]*/导出函数帖子(网址,参数){ 0返回新的承诺(解析,拒绝)={ axios.post(url,QS.stringify(params)).然后(RES={ resolve(RES . data);}) .catch(err={ reject(err。数据)})};}总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。