文学起点网
当前位置: 首页 文学百科

vue axios二次封装(vue中Axios的封装和API接口的管理)

时间:2023-07-15 作者: 小编 阅读量: 1 栏目名: 文学百科

他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御XSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。例如超过了10s,就会告知用户当前请求超时,请刷新等。其实,你前端的请求可以携带token,但是后台可以选择不接收啊!

一、axios的封装

在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御XSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果还对axios不了解的,可以移步axios文档。

安装

npm install axios; // 安装axios复制代码

引入

一般我会在项目的src目录中,新建一个request文件夹,然后在里面新建一个http.js和一个api.js文件。http.js文件用来封装我们的axios,api.js用来统一管理我们的接口。

// 在http.js中引入axiosimport axios from 'axios'; // 引入axiosimport QS from 'qs'; // 引入qs模块,用来序列化post类型的数据,后面会提到// vant的toast提示框组件,大家可根据自己的ui组件更改。import { Toast } from 'vant'; 复制代码

环境的切换

我们的项目环境可能有开发环境、测试环境和生产环境。我们通过node的环境变量来匹配我们的默认的接口url前缀。axios.defaults.baseURL可以设置axios的默认请求地址就不多说了。

// 环境的切换if (process.env.NODE_ENV == 'development') {axios.defaults.baseURL = '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.timeout = 10000;复制代码

post请求头的设置

post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置post的请求头为application/x-www-form-urlencoded;charset=UTF-8

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';复制代码

  • 请求拦截

我们在发送请求前可以进行一个请求的拦截,为什么要拦截呢,我们拦截请求是用来做什么的呢?比如,有些请求是需要用户登录之后才能访问的,或者post请求的时候,我们需要序列化我们提交的数据。这时候,我们可以在请求被发送之前进行一个拦截,从而进行我们想要的操作。

请求拦截

// 先导入vuex,因为我们要使用到里面的状态对象// vuex的路径根据自己的路径去写import store from '@/store/index';// 请求拦截器axios.interceptors.request.use(config => {// 每次发送请求之前判断vuex中是否存在token// 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况 // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断const token = store.state.token;token && (config.headers.Authorization = token);return config;},error => {return Promise.error(error); })复制代码

这里说一下token,一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。这时候或许有些小伙伴会有疑问了,就是每个请求都携带token,那么要是一个页面不需要用户登录就可以访问的怎么办呢?其实,你前端的请求可以携带token,但是后台可以选择不接收啊!

响应的拦截

// 响应拦截器axios.interceptors.response.use(response => {// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据// 否则的话抛出错误 if (response.status === 200) {return Promise.resolve(response);} else {return Promise.reject(response);}},// 服务器状态码不是2开头的的情况 // 这里可以跟你们的后台开发人员协商好统一的错误状态码// 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等 // 下面列举几个常见的操作,其他需求可自行扩展 error => {if (error.response.status) {switch (error.response.status) {// 401: 未登录 // 未登录则跳转登录页面,并携带当前页面的路径 // 在登录成功后返回当前页面,这一步需要在登录页操作。case 401:router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath} }); break; // 403 token过期 // 登录过期对用户进行提示 // 清除本地token和清空vuex中token对象 // 跳转登录页面case 403: Toast({ message: '登录过期,请重新登录', duration: 1000, forbidClick: true }); // 清除token localStorage.removeItem('token'); store.commit('loginSuccess', null); // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面setTimeout(() => {router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath}});}, 1000);break;// 404请求不存在 case 404: Toast({ message: '网络请求不存在', duration: 1500, forbidClick: true }); break; // 其他错误,直接抛出错误提示 default: Toast({ message: error.response.data.message, duration: 1500, forbidClick: true }); } return Promise.reject(error.response); } } });复制代码

响应拦截器很好理解,就是服务器返回给我们的数据,我们在拿到之前可以对他进行一些处理。例如上面的思想:如果后台返回的状态码是200,则正常返回数据,否则的根据错误的状态码类型进行一些我们需要的错误,其实这里主要就是进行了错误的统一处理和没登录或登录过期后调整登录页的一个操作。

要注意的是,上面的Toast()方法,是我引入的vant库中的toast轻提示组件,你根据你的ui库,对应使用你的一个提示组件。

封装get方法和post方法

我们常用的ajax请求方法有get、post、put等方法,相信小伙伴都不会陌生。axios对应的也有很多类似的方法,不清楚的可以看下文档。但是为了简化我们的代码,我们还是要对其进行一个简单的封装。下面我们主要封装两个方法:get和post。

get方法:我们通过定义一个get函数,get函数有两个参数,第一个参数表示我们要请求的url地址,第二个参数是我们要携带的请求参数。get函数返回一个promise对象,当axios其请求成功时resolve服务器返回 值,请求失败时reject错误值。最后通过export抛出get函数。

/** * get方法,对应get请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] */export function get(url, params){return new Promise((resolve, reject) =>{axios.get(url, {params: params}).then(res => { resolve(res.data); }).catch(err =>{ reject(err.data)}) });}复制代码

post方法:原理同get基本一样,但是要注意的是,post方法必须要使用对提交从参数对象进行序列化的操作,所以这里我们通过node的qs模块来序列化我们的参数。这个很重要,如果没有序列化操作,后台是拿不到你提交的数据的。这就是文章开头我们import QS from 'qs';的原因。如果不明白序列化是什么意思的,就百度一下吧,答案一大堆。

/*** post方法,对应post请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/export function post(url, params) { return new Promise((resolve, reject) => { axios.post(url, QS.stringify(params)) .then(res => { resolve(res.data); }) .catch(err =>{ reject(err.data) }) });}复制代码

这里有个小细节说下,axios.get()方法和axios.post()在提交数据时参数的书写方式还是有区别的。区别就是,get的第二个参数是一个{},然后这个对象的params属性值是一个参数对象的。而post的第二个参数就是一个参数对象。两者略微的区别要留意哦!

axios的封装基本就完成了,下面再简单说下api的统一管理。

整齐的api就像电路板一样,即使再复杂也能很清晰整个线路。上面说了,我们会新建一个api.js,然后在这个文件中存放我们所有的api接口。

  • 首先我们在api.js中引入我们封装的get和post方法

/*** api接口统一管理 */import { get, post } from './http'复制代码

现在,例如我们有这样一个接口,是一个post请求:

http://www.baiodu.com/api/v1/users/my_address/address_edit_before复制代码

我们可以在api.js中这样封装:

export const apiAddress = p => post('api/v1/users/my_address/address_edit_before', p);复制代码

我们定义了一个apiAddress方法,这个方法有一个参数p,p是我们请求接口时携带的参数对象。而后调用了我们封装的post方法,post方法的第一个参数是我们的接口地址,第二个参数是apiAddress的p参数,即请求接口时携带的参数对象。最后通过export导出apiAddress。

然后在我们的页面中可以这样调用我们的api接口:

import { apiAddress } from '@/request/api';// 导入我们的api接口export default {name: 'Address',created () { this.onLoad(); }, methods: {// 获取数据onLoad() { // 调用api接口,并且提供了两个参数apiAddress({type: 0,sort: 1}).then(res => { // 获取数据成功后的其他操作 ………………})}}}复制代码

其他的api接口,就在pai.js中继续往下面扩展就可以了。友情提示,为每个接口写好注释哦!!!

api接口管理的一个好处就是,我们把api统一集中起来,如果后期需要修改接口,我们就直接在api.js中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦。关键是,万一修改的量比较大,就规格gg了。还有就是如果直接在我们的业务代码修改接口,一不小心还容易动到我们的业务代码造成不必要的麻烦。

好了,最后把完成的axios封装代码奉上。

/**axios封装 * 请求拦截、相应拦截、错误统一处理 */import axios from 'axios';import QS from 'qs';import { Toast } from 'vant';import store from '../store/index'// 环境的切换if (process.env.NODE_ENV == 'development') {axios.defaults.baseURL = '/api';} else if (process.env.NODE_ENV == 'debug') {axios.defaults.baseURL = '';} else if (process.env.NODE_ENV == 'production') {axios.defaults.baseURL = 'http://api.123dailu.com/';}// 请求超时时间axios.defaults.timeout = 10000;// post请求头axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';// 请求拦截器axios.interceptors.request.use(config => { // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了 // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 const token = store.state.token;token && (config.headers.Authorization = token);return config;},error => {return Promise.error(error);})// 响应拦截器axios.interceptors.response.use(response => {if (response.status === 200) {return Promise.resolve(response);} else {return Promise.reject(response);}}, // 服务器状态码不是200的情况error => {if (error.response.status) {switch (error.response.status) {// 401: 未登录// 未登录则跳转登录页面,并携带当前页面的路径// 在登录成功后返回当前页面,这一步需要在登录页操作。case 401:router.replace({path: '/login',query: { redirect: router.currentRoute.fullPath }}); break; // 403 token过期// 登录过期对用户进行提示// 清除本地token和清空vuex中token对象// 跳转登录页面case 403:Toast({message: '登录过期,请重新登录',duration: 1000,forbidClick: true});// 清除tokenlocalStorage.removeItem('token');store.commit('loginSuccess', null);// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 setTimeout(() => {router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath}});}, 1000);break;// 404请求不存在case 404:Toast({message: '网络请求不存在',duration: 1500,forbidClick: true});break;// 其他错误,直接抛出错误提示default:Toast({message: error.response.data.message,duration: 1500,forbidClick: true});}return Promise.reject(error.response);}});/*** get方法,对应get请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/export function get(url, params){return new Promise((resolve, reject) =>{axios.get(url, {params: params}).then(res => {resolve(res.data);}).catch(err => {reject(err.data)})});}/*** post方法,对应post请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/export function post(url, params) {return new Promise((resolve, reject) => {axios.post(url, QS.stringify(params)).then(res => {resolve(res.data);}).catch(err => {reject(err.data)})});}复制代码

作者:愣锤

链接:https://juejin.im/post/5b55c118f265da0f6f1aa354

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    推荐阅读
  • 苏州旅游攻略景点必去(苏州旅游必去景点有哪些)

    位于苏州市东北街一百七十八号,始建于明朝正德年间。虎丘是AAAAA级景区及全国文明单位,首批十佳文明风景旅游区示范点。中午,周庄最为欢闹,游人穿梭熙熙攘攘,船儿来回摇摇荡荡,各地的游客与热情的商铺融为一体,热闹非凡,安静的古镇着实多了些欢闹的气息。狮子林为苏州四大名园之一,位于苏州市市城东北园林路。

  • 买的玉米种子是瘪的(去年买的玉米种子剩了很多)

    去年买的陈玉米种子建议不要用针对去年的陈玉米种子,大多情况下不建议再次使用,会影响到玉米后期的生长和产量情况。陈年的因为保管的问题,可能会出现很多因素影响玉米的出苗率或者后期的生长。陈玉米种子隔了一年后再种植,种子自身水分含量降低,水分降低严重的情况下,影响播种的效率和玉米的后期生长,由于活性降低,即使能出芽,也不一定能出苗。

  • 173.2亿!国庆消费火爆 国庆消费市场

    今年国庆、重阳两节叠加,全省消费市场呈现平衡较快增长态势,服装、家电、汽车等商品消费亮点突出,大众餐饮、旅行休闲、文体娱乐等主要服务消费备受青睐。根据商务部业务统一平台生存必需品监测系统显示,国庆黄金周期间,全省生存必需品市场供应充沛,价格总体平衡。除了买买买,国庆还是婚庆、团圆、会友高峰,各地亲友聚餐、婚寿宴等大众化餐饮生意兴隆。

  • 吴承恩是怎么写出的西游记(吴承恩怎么写出的西游记)

    吴承恩怎么写出的西游记诸葛长青:吴承恩写西游记诸葛长青:吴承恩怎么写出的《西游记》西游记,广泛流传西游记,作者吴承恩西游记,包含了儒释道大智慧那么,吴承恩是怎么写出的《西游记》呢?诸葛长青把自己对吴承恩写《西游记》,研究成。

  • 李逵扮演者(大家一起来看看吧)

    我们一起去了解并探讨一下这个问题吧!李逵扮演者赵小锐的李逵应该算是很多人印象当中的经典所在了,他的李逵也是很粗犷,但是这种粗犷当中却带着细腻,也是因为这个角色,他开始受到了不少的观众的关注和喜爱。其实之前的他也有出演过一些电视剧的,但是可惜的是一直都没能够真正的红起来,是李逵这个角色,让他一夜成名爆火了。

  • 汽车空间大小怎么看轴距(什么因素会影响车内空间)

    大众速腾,长度4655mm,轴距2651mm。看外观就明白了,因为宝马320i是后驱车,发动机采用纵置布局;而大众速腾是前驱车,发动机采用横置布局。而且由于发动机纵置,后驱设计,对于车内空间侵占较为严重,所以宝马320的长轴距实际上对于空间的帮助是“虚高”的。前面我们就提到了,宝马3系采用了后驱,大众速腾采用了前驱。回到我们的主题,通常来说,麦弗逊与扭力梁对于车辆空间的侵占是最小的,而多连杆和双叉臂对于车辆空间侵占是要更大的。

  • 湖南省医保局2015年工作思路与安排 湖南省医疗保障局领导班子组成人员

    督促指导各统筹地区核实提高缴费基数,强化保险费足额征收。继续加强工伤认定参与,把好工伤入口关。认真核实、积极处理群众举报问题,始终保持高压态势。加强生育医疗服务管理,规范生育津贴发放。二是启动实施工伤保险信息系统改造升级,改进工伤职工异地就医联网结算,方便工伤职工救治。三是加强财务、业务数据清理,提高数据质量;通报全省“三险”基金运行分析,指导市州加强基金运行风险管控。

  • 民国最渣四大渣男(民国著名4大渣男)

    当时很多文人在接受自由恋爱的思想时,家中已经有了父母为之安排的妻子。郁达夫一生有过三位妻子,一位同居情人。郁达夫后来还是和王映霞离婚,1940年在新加坡认识了比他小20岁的播音员李莜英,两人很快就同居了。第二任妻子佐藤富子,是个日本女人,为了和郭沫若在一起,不仅改名为“郭安娜”,还和父母断绝了关系。1937年,郭沫若抛弃妻子回国,和女明星于立群同居,两人于2年后再重庆结婚。

  • 电脑怎么连打印机教程(教会你快速学会电脑如何连接打印机的安装使用方法)

    最近很多网友都在私信给小编,小编也无法一一回复,有些问题也无法简约介绍,所以只能在头条文章内与大家共享。

  • 爱吃鸡蛋的注意了这3种鸡蛋不能买(这些鸡蛋没你想的那么好)

    营养均衡的孩子没必要补这种元素;真正缺乏硒,靠富硒蛋补,根本起不了多大作用。这类蛋再好,也别给孩子吃那就是全生或半熟的蛋,比如溏心蛋。一般溏心蛋的加热时间短,不能完全杀死细菌,生蛋液根本没有处理细菌,对于抵抗力低、易感染的宝宝来说,非常容易被细菌感染。