为啥有现成的可以直接用 , 而要二次封装那么麻烦呢?
直接在vue文件中使用axios进行数据请求 , 会造成如下问题
1. 从项目分层的的角度看,业务层中又混入axios的API,缺少分层和模块化 , 不科学
2. 打包后 ,会将vue文件转换为html文件 ,所有请求都在html中,会有黑客将url进行反编译,进行攻击,获取资源,安全性低
3. 当一旦axios不在维护 , 不需要axios作为项目中请求的插件时,只需要改几个文件就行了, 不用满世界的改axios的API
目录结构
├─ src
| ├── api
| | ├── api.js // 返回值和错误统一处理 , 统一管理
| | ├── login.js //模块或页面下的请求
│ ├──request // 基本配置
│ │ ├── http.js //统一处理接口 , 拦截 , 状态处理
│ │ ├── url.js //接口url
http.js
import axios from 'axios';
import qs from 'qs';
import url from './url.js'
/**
* 根据环境变量区分接口的默认地址
*/
switch (process.env.NODE_ENV) {
case 'production':
axios.defaults.baseURL = '生产环境下的公共请求url';
break;
case 'test':
axios.defaults.baseURL = '测试环境下的公共请求url';
break;
default:
axios.defaults.baseURL = url.BASEURL;
}
/**
* 设置超时时间和跨域是否允许携带凭证
*/
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true;
/**
* 设置post请求头; 告知服务器请求主体的数据格式
* x-www-form-urlencoded
*/
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.transformRequest = data => qs.stringify(data); //只对post有作用
/**
* 设置请求拦截器
* 客户端发送请求 - >[请求拦截器] - > 服务器
* TOKEN校验(JWT):接收服务器返回的token , 存储到vuex/本地存储中,每次向服务器发请求,我们应该吧token带上
*/
// axios = axios.create({
// baseURL: BASEURL, // 'https://mock.cangdu.org/mock/5fb233ffbcab7337c1b1c295/example', //请求接口公共部分
// timeout: 5500 //等待时间
// })
axios.interceptors.request.use(
config => {
//假设服务端返回的token , 被存储在本地存储中
//携带token
let token = localStorage.getItem('token') || '';
token && (config.headers.Authorization = token);
return config;
},
err => {
return Promise.reject(err);
}
);
/**
* 响应拦截器
* 服务器返回信息 -> [拦截的统一处理] -> 客户端JS获取到信息
*/
// axios.defaults.validateStatus = status => {
// //自定义响应成功的HTTP状态码
// return /^(2|3)d{2}$/.test(status);
// }
axios.interceptors.response.use(response => {
return response.data
}, error => {
let {
response
} = error;
if (response) {
//起码服务器有返回结果
switch (response.status) {
case 401: //权限 当前请求需要用户验证(一般是未登录)
break;
case 403: //服务器已经理解请求 , 但拒绝执行它(一般TOKEN过期)
localStorage.removeItem('token');
break;
case 404: //找不到地址
break;
}
} else {
//服务器没有返回结果
if (!window.navigator.onLine) {
//断网处理:可以跳转断网页面
return;
} else {
return Promise.reject(error)
}
}
})
export default axios;
url.js
//接口url , 在编译时会打乱 , 反编译也无法获取 , 安全性提高
const BASEURL = 'https://mock.cangdu.org/mock/5fb233ffbcab7337c1b1c295/example';
const loginUrl = '/upload';
const getUrl = '/query'
export default {
getUrl,
loginUrl,
BASEURL
}
api.js
import login from './login.js'
export default {
login
}
login.js
import axios from "../request/http.js"
import url from '../request/url.js'
function loginOfPost(data) {
return axios.post(url.loginUrl, data)
}
function loginOfGet(data) {
return axios.get(url.getUrl, data)
}
export default {
loginOfPost,
loginOfGet
}
根据项目实际需求封装 , 本着业务层与API层分离的构思去封装 , 分模块进行处理 , 易于维护 , 且安全性更高
拓展思考
axios挂载在vue原型上,会污染原型,不建议这样做,但还没有找到更好的解决办法
//如果项目中用到了vuex , 可以尝试使用vuex这么玩
import axios from 'axios' const store = new Store() store.$axios = axios
最后
推荐几篇博客:
http://www.xiaoheidiannao.com/219695.html
https://blog.csdn.net/weixin_44287777/article/details/102974636
├─ src | ├── apis | | ├── api.js // 返回值和错误统一处理 , 统一管理| | ├── login.js //模块或页面下的请求│ ├──request // 基本配置│ │ ├── service.js //统一处理接口 , 拦截 , 状态处理│ │ ├── common.js //传参处理 │ │ ├── apiUrl.js //接口url