前言:
axios封装,通过配置请求地址、请求拦截器、响应拦截器、请求方法封装、api接口模块化管理,提高代码的可读性,方便维护代码。
一、结构目录
http.js用于封装axios的配置,包括请求地址、请求拦截器、响应拦截器等。
request.js用于请求方法的封装,包括get、post、文件下载等。
index.js用于api接口统一管理的出口文件。
modules文件夹下面存放各个模块的接口,包括用户、文章、公共数据等。
二、http.js
用于封装axios的配置,包括请求地址、请求拦截器、响应拦截器等。
// 1、引入
import axios from 'axios'
import router from '../router';
import store from '../store'
import { getToken } from '../utils/user'
import { Notification } from 'element-ui';
// 2、配置请求地址公共部分
// 一般项目中存在开发环境、测试环境、生产环境,以及后端人员开发环境的地址,因此需要动态配置请求地址。
if (process.env.NODE_ENV === 'development') {
axios.defaults.baseURL = 'http://localhost'
} else if (process.env.NODE_ENV === 'debug') {
axios.defaults.baseURL = ''
} else if (process.env.NODE_ENV === 'production') {
axios.defaults.baseURL = ''
}
// 3、请求超时时间
// 当请求后端接口超时后,检测到并且提示用户进行相关操作。
axios.defaults.timeout = 5000;
// 4、post请求头
// POST请求头常用类型包含:根据自己的项目自行设置。
// application/x-www-form-urlencoded
// application/json
// text/xml
// multipart/form-data
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
// 5、请求拦截器
// 请求拦截,就是我们在发送请求之前,先做一些事情,做完之后再调取后端接口。例如用户身份验证,我们需要将用户的token值放在请求头中,后端拿到token后进行校验等操作。
axios.interceptors.request.use(
config => {
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
// 此处将token存放在Vuex中,进行查询和保存。
if (store.getters.token) {
config.headers['token'] = getToken()
}
return config
},
error => {
console.log(error) // for debug
return Promise.reject(error)
}
)
// 6、响应拦截器
// 请求完后端接口后返回响应数据,我们需要对这个响应进行校验和异常处理,方便及时抛出错误。
axios.interceptors.response.use(
response => {
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是200的情况
error => {
debugger
// Network Error:网络连接失败。
// 服务器连接失败,跳转至服务器连接失败显示界面。
// 在服务器连接成功后返回当前页面
if (error.message === 'Network Error') {
Notification({
title: '提示',
showClose: true,
message: '服务器连接失败,请稍后再试!',
type: 'error'
});
router.replace({
path: '/network_error',
query: {
redirect: router.currentRoute.fullPath
}
});
}
// 以下需根据后端接口统一规定哪些错误方式,进行异常错误处理。
if (error.response.status) {
switch (error.response.status) {
//401:未登录,请求要求用户的身份认证
//未登录则跳转登录页面,并携带当前页面的路径
//在登录成功后返回当前页面,这一步需要在登录页操作
case 401:
Notification({
title: "提示",
showClose: true,
message: '请登录!',
type: 'error'
});
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token过期,服务器理解请求客户端的请求,但是拒绝执行此请求
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Notification({
title: "提示",
showClose: true,
message: '登录过期,请重新登录',
type: 'error'
});
//清除token
//跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
//404请求不存在,服务器无法根据客户端的请求找到资源
case 404:
Notification({
title: "提示",
showClose: true,
message: '网络请求不存在',
type: 'error'
});
break;
//其他错误,直接抛出错误提示
default:
Notification({
title: "提示",
showClose: true,
message: error.response.data.message,
type: 'error'
});
}
}
return Promise.reject(error.response);
}
);
export default axios
三、request.js
此处将GET、POST等常用方法进行封装,同时为了以后方便封装一些其他请求,例如下载文件、webSocket等方法。
import axios from "./http.js"
/**
* 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, params)
.then(res => {
resolve(res.data);
}).catch(err => {
reject(err.data);
})
});
}
四、index.js
index.js是一个api接口的出口,这样就可以把api接口根据功能划分为多个模块,利于多人协作开发。
import article from './modules/user';
export default {
article,
}
五、article.js
article.js是某个功能模块的api接口。
import { get, post } from '../request'
const article = {
getList:params=>get('/getArticleList',params)
}
export default article;
六、实例调用
为了方便在组件中调用接口,我们将接口挂载到vue的原型中。
main.js文件:
import api from './api' // 导入api接口
Vue.prototype.$api = api; // 将api挂载到vue的原型上
组件:
<template>
<div id="app">
<button @click="handleButton">按钮</button>
</div>
</template>
<script>
export default {
name: "App",
methods: {
handleButton() {
this.$api.article
.getArticleList({pageIndex:1,pageSize:10})
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err);
});
},
},
};
</script>