.env
开始之前vue管理系统中的axios的basUrlr如果不写一般会去找.env的文件 .env.company
NODE_ENV = ''
NODE_TYPE = ''
ORG_NAME = ''
ORG_CODE = ''
VUE_APP_BASE_URL = 'ip地址'
.env.beijing
VUE_APP_BASE_URL = 'ip地址'
.env.company
VUE_APP_BASE_URL = 'ip地址'
axios.defaults
axios.defaults.baseURL = 是强制改变ip地址
方法一
如下,请求可以分为三部分
1.index.js中封装各类的请求,如get,post,put,delete,upload,login,logout,refresh等等请求。 2.request.js是创建一个axios赋予基础参数,并且添加响应拦截器。
3.requestUrl.js是用来抽取一个基础的url参数,并且做一个拼接。
下面按照这三个文件的引用顺序做一个单个文件的代码拆分分析
requestUrl.js
/**
* 请求地址统一处理/组装
* @param {*} actionName action方法名称
*/
export default function(actionName) {
let url = process.env.VUE_APP_BASE_URL || "http://***.com"
return url + actionName
}
request.js
/* jshint esversion: 6 */
import axios from "axios";
import Vue from "vue";
import router from "../router/index";
import store from "../store";
import requestUrl from "./requestUrl";
// 创建axios实例
const request = axios.create({
timeout: 10000 * 10,
});
// response拦截器
request.interceptors.response.use(
(response) => {
// 101 用户名或密码错误
// 102 REFRESH-TOKEN不存在/失效
// 103 token验证失败
// 104 未登录
let code = response.data.code;
if(code == 102 || (!store.state.refreshing && code == 104)){
// 退出登陆
store.commit("logout");
router.replace({ name: "login" });
}
if (!store.state.refreshing && code == 103) {
// token失效 刷新token
Vue.prototype.ajax.refresh();
response.data.msg = "长时间页面未更新,尝试重新提交或刷新页面";
}
return response.data;
},
(error) => {
return Promise.reject(error);
}
);
export { request, requestUrl };
复制代码
index.js
1.里面需要引入的模块如下
import { request, requestUrl } from "./request";
import store from "../store/index";
import Vue from "vue";
import qs from "qs";
复制代码
需要一个公共axios请求方法
/**
* axios请求封装
* @param {*} opt
*/
function send(opt, resolve, reject, success, error, complete) {
// 获取refresh_token时,延迟请求
if (store.state.refreshing) {
setTimeout(() => {
send(opt, resolve, reject, success, error, complete);
}, 300);
return;
}
let nowtime = new Date().getTime() / 1000;
//overtime是登录成功之后端返回的时间加上登录的时间戳
let overtime = Number(store.state.overtime);
// 如果登陆时间大于8小时则直接退出
if (store.state.token && overtime && nowtime - overtime > 8 * 3600) {
store.commit("logout");
router.replace({ name: "login" });
return;
}
// 如果登陆时间小于8小时并且超出refreshtoken时间,则刷新token
if (store.state.token && overtime && overtime < nowtime) {
store.commit("changeRefresh", false);//改变store.state.refreshComplate
ajax.refresh(opt, resolve, reject, success, error, complete);
return;
}
if (store.state.refreshComplate) {
let token = store.state.token;
if (token) {
opt.headers.token = token;
}
}
request(opt)
.then((res) => {
resolve(res);
if (success) success(res);
})
.catch((err) => {
reject(err);
if (error) error();
Vue.prototype.$message.error("网络错误,请稍后重试");
})
.finally(() => {
if (complete) complete();
});
}
3.需要封装一个拿取token的方法
function getToken() {
let token = store.state.token;
if (!token) {
store.commit("logout");
Vue.prototype.$message.error("登陆信息失效,请重新登陆");
router.replace({ name: "login" });
}
return token;
}
```js
## 4.定义一个ajax对象在里面封装各种类型的方法,并且导出它
```js
const ajax = {
get(){},
post(){},
put(){},
delete(){},
upload(){},
login(){},
logout(){},
refresh(){},
};
export { ajax };
get方法的封装
const ajax = {
get: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "get",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
params,
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
}
}
post方法的封装
const ajax = {
post: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
put方法的封装
const ajax = {
put: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "put",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
delete方法的封装
const ajax = {
delete: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "delete",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
params,
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
复制代码
upload方法的封装
const ajax = {
upload: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "post",
headers: {
"Content-Type": "multipart/form-data",
token,
},
data: toFormData(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
login方法的封装
const ajax = {
login: (params) => {
store.commit("isRefresh", false);
let opt = {
url: requestUrl("/login"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
logout方法的封装
const ajax = {
logout: () => {
store.commit("isRefresh", false);
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl("/logout"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject, false, false, () => {
store.commit("logout");
});
});
},
}
复制代码
refresh方法的封装
const ajax = {
refresh: (...success) => {
if (store.state.refreshing) return;
store.commit("isRefresh", true);
let opt = {
url: requestUrl("/refresh_token"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"refresh-token": store.state.refresh_token,
},
};
return new Promise((resolve, reject) => {
request(opt)
.then((res) => {
resolve(res);
if (res.code == 0) {
store.commit("setUserInfo", res.data);
if (success) {
if (success[0].headers && success[0].headers.token) {
success[0].headers.token = res.data.token;
}
send(...success);
}
}else{
ajax.logout()
}
})
.catch((err) => {
reject();
Vue.prototype.$message.error("网络错误,请稍后重试");
})
.finally(() => {
store.commit("isRefresh", false);
});
});
},
}
使用 this.ajax.post(url, query)
方法二 挂载在window就可直接使用
// console.log(BASE, "配置文件config/api配置文件");
const HTTTPS = axios.create({
baseURL: BASE.base ? BASE.base : window.location.origin ,
timeout: 10000
})
HTTTPS.interceptors.request.use(config => {
Loading({ type: 1, tipLabel: "加载中..." })
config['Content-Type'] = 'application/x-www-form-urlencoded'
return config
}, error => {
return Promise.reject(error)
})
HTTTPS.interceptors.response.use(response => {
// console.log(response,"response");
switch (response.data.code) {
case -1:
console.log('网络连接未响应');
break;
case 416:
sessionStorage.removeItem('userObj')
sessionStorage.removeItem('TOKEN')
sessionStorage.removeItem('RANDOMTOKEN')
sessionStorage.removeItem('access_token')
// window.location.href = "../index.html"
break;
default:
break;
}
return response
}, error => {
// 捕捉错误
return Promise.reject(error)
})
console.log(HTTTPS.defaults,"HTTTPS");
const ajax = {
get(url, query, gather) {
return HTTTPS({
method: 'get',
url: url,
headers: {
'CONFERENCE-AUTH-TOKEN': gather ? gather.isToken ? sessionStorage.getItem('TOKEN') : '' : '',
'CONFERENCE-AUTH-RANDOM': gather ? gather.isToken ? sessionStorage.getItem('RANDOMTOKEN') : '' : '',
},
params: query
}).catch(e => {
// HTTTPS.defaults.baseURL = WAIBASE.base
// return this.get(url, query, gather)
})
},
post(url, body, gather) {
return HTTTPS({
method: 'post',
url,
headers: {
'CONFERENCE-AUTH-TOKEN': gather ? gather.isToken ? sessionStorage.getItem('TOKEN') : '' : '',
'CONFERENCE-AUTH-RANDOM': gather ? gather.isToken ? sessionStorage.getItem('RANDOMTOKEN') : '' : '',
},
params: Qs.parse(body)
}).catch(e => {
// HTTTPS.defaults.baseURL = WAIBASE.base
// return this.post(url, query, gather)
})
}
}
window['$http'] = ajax
使用: window['$http'].post(CONFIGURL['ROLEDEL'], { roleId: roleId }, gather = { isToken: true })
方法三
request.js
import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message} from 'element-ui';
//1. 创建新的axios实例,
const service = axios.create({
// baseURL:"http://tj139617.asuscomm.com:8201",
baseURL:'https://api.aigou.store/api',
// 超时时间 单位是ms
timeout: 5 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/json;charset=utf-8', //配置请求头
// 'XX-Api-Version':'1.0',
// 'XX-Device-Type':'pc'
}
const tokenHead = sessionStorage.getItem('tokenHead')
const token =sessionStorage.getItem('token');//这里取token之前,需要先拿到token,存一下
if(token){
config.headers['Authorization']= tokenHead+token; //如果要求携带在请求头中
}
return config
}, error => {
Promise.reject(error)
})
// 3.响应拦截器
service.interceptors.response.use(response => {
return response
}, error => {
/***** 接收到异常响应的处理开始 *****/
if (error && error.response) {
// 1.公共错误处理
// 2.根据响应码具体处理
switch (error.response.code) {
case 400:
error.message = '错误请求'
break;
case 401:
error.message = '未授权,请重新登录'
break;
case 403:
error.message = '拒绝访问'
break;
case 404:
error.message = '请求错误,未找到该资源'
window.location.href = "/NotFound"
break;
case 405:
error.message = '请求方法未允许'
break;
case 408:
error.message = '请求超时'
break;
case 500:
error.message = '服务器端出错'
break;
case 501:
error.message = '网络未实现'
break;
case 502:
error.message = '网络错误'
break;
case 503:
error.message = '服务不可用'
break;
case 10001:
error.message = '网络超时'
break;
case 505:
error.message = 'http版本不支持该请求'
break;
default:
error.message = `连接错误${error.response.status}`
}
} else {
// 超时处理
if (JSON.stringify(error).includes('timeout')) {
Message.error('服务器响应超时,请刷新当前页')
}
error.message = '连接服务器失败'
}
Message.error(error.message)
/***** 处理结束 *****/
//如果不需要错误处理,以上的处理过程都可省略
return Promise.resolve(error.response)
})
//4.导入文件
export default service
http.js 引入request
import request from './request'
const http ={
/**
* methods: 请求
* @param url 请求地址
* @param params 请求参数
*/
get(url,params){
const config = {
method: 'get',
url:url
}
if(params) config.params = params
return request(config)
},
post(url,params){
const config = {
method: 'post',
url:url
}
if(params) config.data = params
return request(config)
},
put(url,params){
const config = {
method: 'put',
url:url
}
if(params) config.params = params
return request(config)
},
delete(url,params){
const config = {
method: 'delete',
url:url
}
if(params) config.params = params
return request(config)
}
}
//导出
export default http
某个模块创建方法
import http from '../utils/http';
// 申请入驻列表
export function temporaryList(params){
return http.get(`/mall-admin/shop/temporaryList`,params)
}
// 店铺统计
export function getshopList(params){
return http.get(`/mall-admin/statistics/shopList`,params)
}
test.vue
import { temporaryList } from "@/api/cations.js";
let res = await temporaryList(params);
方法四
request.js
import axios from "axios";
import Vue from "vue";
import $store from "../store";
import $router from "../router";
// 判断当前的运行环境 process.env.NODE_ENV
// isDev 为真 开发环境 --- npm run serve
// isDev 为假 非开发环境(测试环境,生产环境)- npm run build
// const isDev = process.env.NODE_ENV === 'development'
let errorCount = 0;
let errorTimer = null;
const request = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
});
// 请求拦截器 - 所有的请求开始之前先到此处
request.interceptors.request.use(
(config) => {
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器 --- 所有请求的相应先到此处
request.interceptors.response.use(
(response) => {
// console.log(response.data.data)
// 可以设置 加载的动画效果 的隐藏
if (response.data.code == "10001" && $store.state.token) {
Vue.prototype.ajax.logout();
localStorage.removeItem("login");
$store.commit("logout");
Vue.prototype.$message({ message: "登陆失效,请重新登陆" });
setTimeout(() => {
$router.replace({ path: "/" });
}, 1000);
}
return response.data;
},
(error) => {
if (!errorTimer) {
Vue.prototype.$message("链接服务器失败,请查看网络环境或配置文件");
errorTimer = setTimeout(()=>{
clearTimeout(errorTimer)
errorTimer = null;
errorCount = 0;
},15000)
}
errorCount++;
if (errorCount > 3 || $store.state.token) {
Vue.prototype.ajax.logout();
localStorage.removeItem("login");
$store.commit("logout");
setTimeout(() => {
$router.replace({ path: "/" });
errorCount = 0;
}, 1000);
}
return Promise.reject(error);
}
);
export default request;
ajax.js
import request from "./request";
import $store from "@/store/index";
import qs from "qs";
const ajax = {
setBase: (url) => {
request.defaults.baseURL = url
},
getBase: () => {
return request.defaults.baseURL
},
get: (url, params) => {
return request({
url,
method: "get",
headers: {
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": $store.state.token || ""
},
params
})
},
post: (url, params,isQs) => {
return request({
url,
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": $store.state.token || ""
},
data:isQs ? params : qs.stringify(params)
})
},
login: (params) => {
return request({
url: "/login",
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": ""
},
data: qs.stringify(params)
})
},
logout: () => {
return request({
url: "/logout",
method: "get",
headers: {
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": $store.state.token || ""
}
})
},
other: (url) => {
return request({
baseURL: url,
method: "get",
headers: {
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": $store.state.token || ""
}
})
},
// 上传
uploadList:(params) =>{
return request({
url:'/upload',
method:"post",
headers:{
"XX-Api-Version": "1.0",
"XX-Device-Type": $store.state.device,
"XX-Token": $store.state.token || ""
},
data: params
})
},
// 分类管理 - 列表
category:() =>{
return request({
url:"/admin/question/category",
method:"get",
headers:{
"XX-Api-Version":"1.0",
"XX-Device-Type":$store.state.device,
"XX-Token":$store.state.token
}
})
},
}
export default ajax;
main.js
import ajax from './api/ajax'
Vue.prototype.ajax = ajax;