Vue项目中封装axios请求方法(包括请求拦截)

    xiaoxiao2022-07-07  227

    本篇文章将对项目中如何封装axios常用的请求方法进行介绍,其中包括最容易出问题的post请求的解释,包括一些请求格式和参数格式不一致问题的解决;


    通用配置

    这些配置是在axios官方文档中没有列出来的,主要是post方法的内容类型的定义,不配置的话经常会出现请求提交失败或者数据没有正常提交的问题,这些一般都是前后端采用的post的数据格式不一致导致的。

    axios.defaults.timeout = 15000; //超时响应 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; // 配置请求头(推荐) // axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8'; // 配置请求头 axios.defaults.baseURL = $core.use('http'); //确认协议和地址 axios.defaults.withCredentials = true; // axios 默认不发送cookie,需要全局设置true发送cookie

    1. get请求

    axios中常见的get/delete请求,也称作query请求:

    一般发送请求是这么写(不推荐):

    axios.get('/user?id=12345&name=user') .then(function (res) { console.log(res); }).catch(function (err) { console.log(err); });

    但是为了方便全局统一调用封装的axios,我一般采用(推荐)

    axios.get('/user', { //params参数必写 , 如果没有参数传{}也可以 params: { id: 12345, name: user } }) .then(function (res) { console.log(res); }) .catch(function (err) { console.log(err); });

    2. post/put/patch请求

    传参方式大致用的有3种

    (1) 传参格式为 formData

    (全局请求头:‘Content-Type’= ‘application/x-www-form-urlencoded’)

    (request的Header:‘Content-Type’= ‘multipart/form-data’)

    var formData=new FormData(); formData.append('user',123456); formData.append('pass',12345678); axios.post("/notice",formData) .then((res) => {return res}) .catch((err) => {return err})

    (2) 传参格式为 query 形式

    (全局请求头:‘Content-Type’= ‘application/x-www-form-urlencoded’)

    (request的Header:‘Content-Type’= ‘application/x-www-form-urlencoded’)

    第一种情况:使用$qs.stringify

    import Qs from 'qs' //引入方式 Vue.prototype.$qs = Qs //全局加载 this.$qs.stringify(data); //使用方式 this.$qs.parse(data); //使用方式 var readyData=this.$qs.stringify({ id:1234, name:user }); axios.post("/notice",readyData) .then((res) => {return res}) .catch((err) => {return err})

    (3) 传参格式为raw (JSON格式)

    第一种情况: axios将JavaScript对象序列化为JSON

    (全局请求头:‘Content-Type’= ‘application/x-www-form-urlencoded’)

    (request的Header:‘Content-Type’= ‘application/json;charset=UTF-8’)

    var readyData={ id:1234, name:user }; axios.post("/notice",readyData) .then((res) => {return res}) .catch((err) => {return err})

    第二种情况:

    (全局请求头:‘Content-Type’= ‘application/json;charset=UTF-8’)

    (request的Header:‘Content-Type’= ‘application/json;charset=UTF-8’)

    var readyData=JSON.stringify({ id:1234, name:user }); axios.post("/notice",readyData) .then((res) => {return res}) .catch((err) => {return err})

    下面给出常用方法的封装,可以直接用在项目中,并列出了可能会遇到的问题解决

    下面所有的提示都是基于iview的提示控件,但是一个项目如果有多个UI库就会引起很多冲突,所以建议大家只用一个UI组件库,根据自己项目情况修改提示。

    /** axios封装 * 请求拦截、相应拦截、错误统一处理 */ // import service from 'axios' import axios from 'axios' import QS from 'qs' // import { Toast } from 'vant' import router from '@/router' import store from '../store/index' let serviceConfig = 'http://192.168.31.69:8080' // const axios = service.create({ // baseURL: serviceConfig // api的base_url // /* baseURL: "http://192.168.0.107:9090", */ // api的base_url // }) // 环境的切换 if (process.env.NODE_ENV === 'development') { axios.defaults.baseURL = serviceConfig // 'api' // axios.defaults.baseURL = 'api' } else if (process.env.NODE_ENV === 'debug') { axios.defaults.baseURL = '' } else if (process.env.NODE_ENV === 'production') { axios.defaults.baseURL = serviceConfig // axios.defaults.baseURL = '/api' } // 请求超时时间 axios.defaults.timeout = 2000 // 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是过期的,所以在响应拦截器中要对返回状态进行判断 config.withCredentials = true 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: this.$Modal.info({ content: '登录过期,请重新登录', duration: 1 }) // 清除token localStorage.removeItem('token') store.commit('loginSuccess', null) // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 setTimeout(() => { router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }) }, 1000) break // 404请求不存在 case 404: this.$Modal.erro({ content: '网络请求不存在', duration: 1 }) break // 其他错误,直接抛出错误提示 default: this.$Modal.erro({ content: error.response.data.message, duration: 1.5 }) } return Promise.reject(error.response) } } ) /** * get方法,对应get请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] */ export const 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 const post = (url, ...params) => { return new Promise((resolve, reject) => { axios //QS.stringify(params)关于这个函数会输出什么结果大家可以自行尝试一下,结果会让你惊喜,也可以自己单独传一个对象进去测试一下 .post(url, QS.stringify(...params)) .then(res => { resolve(res.data) }) .catch(err => { reject(err.data) }) }) } /** * delet方法,对应delett请求 * @param {String} url [请求的url地址] * delete关键字会和vue系统关键字冲突,所以这里用delet代替 * delete用于删除,参数一般带在url */ export const delet = url => { return new Promise((resolve, reject) => { axios .delete(url) .then(res => { resolve(res.data) }) .catch(err => { reject(err.data) }) }) } /** * patch方法,对应patch请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] * 这里根据需求适应了formdata的格式,也可以跟post用一样的封装 */ export const patch = (url, params) => { // 将数据转换为formData格式 // 正常情况下可以直接使用参数对象进行patch,如果出错可以尝试转换form Data var formData = new FormData() formData.append('username', params.username) formData.append('password', params.password) return new Promise((resolve, reject) => { axios .patch(url, formData) .then(res => { resolve(res.data) }) .catch(err => { reject(err.data) }) }) }
    最新回复(0)