之前项目的axios数据请求基本都是写在各组件方法内,如项目接口变动要修改url地址等参数会比较为麻烦,不易维护,决定对axios进行封装并将接口统一管理。
一、新建函数文件:
在vue-cli工程内新建axios-request.js、axios-api.js,其中aixos-request.js用于对axios进行封装,axios-api.js用于接口的统一管理,两个的文件位置根据自身的工程目录来定,我的是存放在src文件夹下的axios文件夹内。
二、对axios进行封装:
// axios-request.js import Vue from 'vue' import Toast from 'muse-ui-toast' /* 引入muse-ui的Toast插件 */ import axios from 'axios' import qs from 'qs' /* 引入qs依赖包,对传参数据序列化 */ Vue.use(Toast, { time: 5000 /* 设置Toast显示5s,防止用户没有注意到 */ }) /* 创建axios实例 */ const axiosService = axios.create({ baseURL: process.env.API_HOST, /* 在config/dev.evn.js、prod.evn.js里面进行配置 */ timeout: 5000 /* 设置超时时间为5s */ }) /* request拦截器 ==> 对请求参数进行处理 */ axiosService.interceptors.request.use( config => { config.method === 'post' ? config.data = qs.stringify({...config.data}) : config.params = {...config.params} /* 判断method是否为post,为post则对参数进行序列化,不为post择不进行序列化 */ config.headers['Content-Type'] = 'application/x-www-form-urlencoded' return config }, error => { Toast.error('错误,请重新操作...') Promise.reject(error) }) /* respone拦截器 ==> 对响应做处理 */ axiosService.interceptors.response.use( response => { if (response.data) { return response.data } else { Toast.error('数据错误,请重试...') } }, error => { /* 判断error的status代码,并将对应的信息告知用户 */ let text = '' let err = JSON.parse(JSON.stringify(error)) if (err.response.status) { switch (error.response.status) { case 400: text = '请求错误(400),请重新申请' break case 401: text = '登录错误(401),请重新登录' return this.$router.replace('/Login') case 403: text = '拒绝访问(403)' break case 404: text = '请求出错(404)' break case 408: text = '请求超时(408)' break case 500: text = '服务器错误(500),请重启软件或切换功能页!' break case 501: text = '服务未实现(501)' break case 502: text = '网络错误(502)' break case 503: text = '服务不可用(503)' break case 504: text = '网络超时(504)' break case 505: text = 'HTTP版本不受支持(505)' break default: text = '网络连接出错' } } else { text = '连接服务器失败,请退出重试!' } Toast.error(text) return Promise.reject(error) } ) /* 将写好的axios实例暴露出去 */ export default axiosService
这里使用了muse-ui的Toast插件用于用户提示。
如果后台需要前端发送时携带token,应在axiosService.interceptors.request.use的config内增加相关内容,我的项目中没有运用到token,简单的形式参考下面的代码:
1 if (store.state.token) { // 判断是否存在token,如果存在的话,则每个http header都加上token 2 config.headers.Authorization = `token ${store.state.token}`; 3 }
三、对接口进行统一管理:
// axios-api.js import axiosService from './axios-request' /* 从axios-request.js内引入axiosService */ /* 下面是POST形式 */ export const userLogin = data => { return axiosService({ url: '/XXXX/user/xxxx', /* 根据实际接口地址来写 */ method: 'post', data }) } /* 下面是GET形式 */ export const userInfo = params=> { return axiosService({ url: '/XXXX/user/XXXXX.action', method: 'get', params }) }
这里要注意下,post参数放在data内,get参数放在params内!
四、在组件内使用写好的接口:
下面是根据我的工程写的一个登录接口,仅供参考:
1 import { userLogin } from '../../axios/axios-api' /* 引入登录接口函数 */ 2 methods: { 3 async login () { 4 this.loginLoading = true 5 let userName = this.userName 6 let passWord = this.passWord 7 let params = { 8 username: userName, 9 password: passWord 10 } 11 if (!userName || !passWord) { 12 this.loginLoading = false 13 this.$toast.error('账号或密码不能为空') 14 } else { 15 if ((userName.length < 51) && (passWord.length < 51)) { 16 let res = await userLogin(params) 17 this.loginBack(res) 18 } else { 19 this.loginLoading = false 20 this.$toast.error('账号或密码输入字符不能超过50位') 21 } 22 } 23 }, 24 loginBack (res) { 25 let resBack = res.Back 26 let resData = res.Data 27 if (resBack === '1') { 28 ...... 29 } else { 30 ...... 31 } 32 } 33 }
使用这种方式,需要注意的是方法内的函数需要时用: async await格式;
当然也可以不将接口统一管理而只用axios封装在组件内写函数:
1 import axiosService from '../../../../axios/axios-request' /* 这里直接引入axios封装 */ 2 3 methods: { 4 submitInfo () { 5 let userName = localStorage.getItem('xyz') 6 let dkId = this.nowLand.id 7 let water = this.nowLand.water 8 let status = this.nowLand.status 9 let params = { 10 usename: userName, 11 dkid: dkId, 12 appwater: water 13 } 14 this.$confirm('是否提交申请?', '提示', { 15 type: 'warning' 16 }).then(({ result }) => { 17 if (result) { 18 if (status === 0) { 19 ...... 20 } else { 21 axiosService({ 22 url: '/HPGQ/waterrecord/addWaterRecord.action', 23 method: 'post', 24 params 25 }).then(this.applyBack) 26 } 27 } else { 28 ...... 29 } 30 }) 31 }, 32 applyBack (res) { 33 ...... 34 } 35 }
以上是个人所用的封装方式,如有错误之处欢迎留言指正~~