一 基于promise 封装 axios
import axios from 'axios' // 工程中引入 axios 模块,用于请求数据
import qs from 'qs' // 工程中引入 qs模块,用于序列化表单,将请求参数转成 form-data 格式
import { Message } from 'element-ui' // 统一采用 element-ui 的提示弹框
import store from 'src/store/store' // 引入Vuex,用于改变 state 的状态
const error = (prop) => { // 封装 element-ui 的 message,用于错误提示
Message.closeAll();
Message({
message: prop,
type: 'error',
duration: 2000
})
}
let instance = axios.create({ // 实例化 axios
baseURL: '/mspapi', // 设置默认请求路径,工程中所有 post 请求方法的请求路径,都会在最前面默认添加 '/mspapi'
method: 'post', // 这样封装的优点是,我们没必要在每一个请求路径前,都写重复的代码(前提是与 服务端 约定好)
headers: { // 请求头
'X-Requested-With': 'XMLHttpRequest',
'x-auth-token': window.localStorage.getItem("_token_") // 以安控为例,与服务端约定,登录成功后的每个请求都携带token (当然登录接口/验证码接口没有token)
}
});
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; // axios 的默认请求头
// POST传参序列化
instance.interceptors.request.use( // request-请求参数拦截器
(config) => {
config.data = qs.stringify(config.data, { arrayFormat: 'brackets' }); // 用于序列化表单,将请求参数转成 form-data 格式
if (config.url.indexOf("/login/dologin") !== -1) { // 如果是登录接口,就特殊判断,请求头不携带 token
config.headers = {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
};
} else { // 除了登录路径,其他都需要携带 token
config.headers = {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'x-auth-token': window.localStorage.getItem("_token_")
};
}
return config; // 返回 封装好 的请求参数
},
(error) => {
return Promise.reject(error) // es6语法 promise reject 返回错误信息
}
)
// 添加返回拦截器
instance.interceptors.response.use((rsp) => { // response-返回数据拦截器
return new Promise((resolve, reject) => { // 实例化一个 promise
// 处理登录状态
if (rsp.status === 203) { // 单独处理状态,前端将 203 转化成 登录超时
rsp.data.code = 101008
} else {
if (rsp.headers["x-auth-token"] && rsp.headers["x-auth-token"] !== "") { // 只有登录接口的 response 返回参数会有 x-auth-token ,前端截取到该 token 存入浏览器本地存储
window.localStorage.setItem("_token_", rsp.headers["x-auth-token"]) // 用于之后的请求参数 携带该 token
}
}
// 若服务器返回特定的通用code(大于100100),则特殊处理;
// 若返回其他错误code,都返回后处理
switch (rsp.data.code) {
case 101005:
case 101008:
window.localStorage.clear(); // 清空本地存储
store.commit("change_timeout", true); // Vuex全局登录超时弹框
break;
case 101006:
window.localStorage.clear(); // 清空本地存储
store.commit("update_license", true); // Vuex全局 license 已更新弹框
break;
case 101002:
case 101001:
window.localStorage.clear(); // 清空本地存储
window.location.href = '/static/505.html'; // 登录的用户,没有查看该页面(或者调取该接口)的权限
break;
default:
resolve(rsp.data) // 其他的 code 值都返回到具体的实例中 处理 (处理相应的业务逻辑)
break;
}
})
}, (err) => { // 如果有异常,则用于 promise 的 reject 回调
console.log(err.response)
if (err.response) {
error('服务器无响应,请联系系统管理员!') // 返回的异常error中,有 response 的,一般是 status为 505 500 501(服务器正在更新)
} else {
error('网络无连接,请检测网络设置!') // 没有response的,说明网络没有连接
}
});
const Post = (url, data) => { // 结合 es6 promise 封装一个Vue全局的 Post 请求方法(该方法的请求路径 会默认添加 '/mspapi')
return new Promise((resolve, reject) => {
data = data ? data : {}; // 处理请求参数,在这里可以 统一处理请求参数
let currentUrl = ''; // 由于工程中不是所有的请求路径都是以 '/mspapi' 开头的
let box = ['/api/login/dologin', '/api/logout', '/api/check_current_user_pwd']; // 所以需要添加一个白名单,用于特殊处理
if (box.indexOf(url) > -1) {
currentUrl = url;
} else {
currentUrl = url;
}
instance.post(currentUrl, data) // 调用我们上面封装好的 axios 实例
.then(rsp => {
resolve(rsp); // resolve 服务端的返回值 response
})
.catch((error) => {
reject(error) // reject 错误信息,使用方法同 Post 。
})
})
};
const Get = (url, data) => { // 封装一个全局的 Get 方法
return new Promise((resolve, reject) => {
instance.get(url, data)
.then(rsp => {
resolve(rsp.data);
})
.catch((error) => {
reject(error)
})
})
}
export { Post, Get, axios };
二 在 main.js 中 全局配置 axios
import { Post } from 'src/tools/axios.js'
Vue.prototype.$post = Post; // 赋值给 Vue 实例原型链,这样所有的 *.vue 文件都可以直接使用 this.$post 调取数据了
注意:如果有 其他方法或属性 也想在Vue全局使用,都可以使用 Vue.prototype 来绑定在 Vue实例上,
不过,一般不推荐这么使用,因为挂载太多的方法会影响性能。
三 在具体的某一个 *.vue 文件中,使用封装好的Post
this.$post("/updateUser/list") // "/mspapi/updateUser/list" 为真正的请求路径
.then(rsp => {
if (rsp.code == 0) {
this.updateList = rsp.data; // 与服务端的约定, code 为 0 时,前端处理具体的页面数据逻辑
} else {
this.$message({
message: rsp.msg, // code 不为 0 且 code 值 不大于 100100 时,前端错误弹框提示 服务端返回的错误信息
type: "error"
});
}
})
.catch(err => {
console.log(err);
});
四 在Vuex 中使用封装好的Post
import { Post } from "src/tools/axios";
import { Message } from 'element-ui';
import router from 'router/index'
const state = {
checkDataList: []
}
const getters = {
}
const actions = {
getCheckDataList({ dispatch, commit }, params) {
Post('/report/checkDataList', params) // 使用方法同上
.then(res => {
if (res.code == 0) {
commit("updateCheckDataList", res.data);
} else {
Message({
type: 'error',
message: res.msg
})
}
})
.catch(err => {
console.log(err)
})
}
}
const mutations = {
updateCheckDataList(state, prop) {
state.checkDataList = prop
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
五 在 axios 中截获 Cookies 并使用HTTP 传递给服务端
https://blog.csdn.net/weixin_...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。