#### 前言:[axios 的基本使用方法](https://www.kancloud.cn/yunye/axios/234845)不赘述。请自行查看文档。
## 背景
业务需求:每当发请求到后端时就触发一个全屏的 loading,多个请求合并为一次 loading,
现在项目中用的是 vue 、axios、cube-ui等,所以文章主要是讲如果使用 axios 和 cube-ui 实现这个功能。
> axios 提供了请求拦截和响应拦截的接口,每次请求都会调用showFullScreenLoading()方法,每次响应都会调用tryHideFullScreenLoading()方法
```
/*请求拦截*/
axios.interceptors.request.use(
config => {
const token = '123412';//自己获取token或者辨别号
config.baseURL ='';
config.timeout = 5000;//请求多少时间超时
showFullScreenLoading()
config.headers['TOKEN']=token;//奖token放入请求头中
return config;
},
error => {
return Promise.reject(err);
}
);
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
tryHideFullScreenLoading()
return response;
},
error => {
return Promise.reject(error)
}
)
```
> 那么showFullScreenLoading tryHideFullScreenLoading()要干的事儿就是将同一时刻的请求合并。声明一个变量needLoadingRequestCount,每次调用showFullScreenLoading方法 needLoadingRequestCount + 1。调用tryHideFullScreenLoading()方法,needLoadingRequestCount - 1。needLoadingRequestCount为 0 时,结束 loading。
```
/*请求合并只出现一次loading*/
let needLoadingRequestCount = 0
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
loading('start')/*loading加载*/
}
needLoadingRequestCount++
}
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return
needLoadingRequestCount--
if (needLoadingRequestCount === 0) {
setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/
}
}
const tryCloseLoading = () => {
if (needLoadingRequestCount === 0) {
loading('end')/*loading加载*/
}
}
/*loading加载*/
function loading (str){
let toast = Toast.$create({/*滴滴弹框*/
txt: 'Loading...',
mask: true,
time: 0
})
if(str=='start'){
toast.show()
}else if(str=='end'){
toast.hide()
}
}
```
> 仔细阅读上方代码会发现有一个300ms的延迟定时器
> setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/
> 当重复请求过多loading页面会出现闪现。而使用上述代码会使得300ms内的请求合并
>最后我们以post为例再次分装
```
export function post(url,data = {}){
return new Promise((resolve,reject) => {
axios.post(url,data,config)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
```
> 前台导出使用即为在main.js中声明
```
import axios from "axios";
import {post,get} from '@/assets/js/http'
Vue.prototype.$post=post;
```
> main.js文件路径引入截图
![](https://box.kancloud.cn/0e8d09d08995e0b51058197a684714f2_1369x501.png)
> 在组件内使用
```
this.$post(url,data).then((data)=>{
console.log(data)
})
```
*****
# :-: **功能加强**
> 如果某个请求不需要 loading 呢,那么发请求的时候加个 showLoading: false的参数就好了。在请求拦截和响应拦截时判断下该请求是否需要loading,需要 loading 再去调用showFullScreenLoading()方法即可。
```
/*请求拦截*/
axios.interceptors.request.use(
config => {
const token = '123412';
config.baseURL ='';
config.timeout = 5000;
if (config.showLoading) {/*功能增加*/
showFullScreenLoading()
}
config.headers['TOKEN']=token;
return config;
},
error => {
return Promise.reject(err);
}
);
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
if(response.config.showLoading){/*功能增加*/
tryHideFullScreenLoading()
}
return response;
},
error => {
Toast.$create({
txt: error.message,//错误信息
type: 'error',
time:2000,
onTimeout: () => {
if(error.config.showLoading){
tryHideFullScreenLoading()//消除loading
}
}
}).show()
return Promise.reject(error)
}
)
```
> 相应的get 和 post 请求封装重新封装(特别注意axios的get,参数不能使用params传值而是直接代入链接尾部)
```
axios.request(配置)
axios.get(url [,config])
axios.delete(url [,config])
axios.head(url [,config])
axios.post(url [,data [,config]])
axios.put(url [,data [,config]])
axios.patch(url [,data [,config]])
```
即
```
axios.get('url?xxx=xxx',{showLoading: false}).then((data)=>{})
```
> 文件封装改变
```
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function get(url, config = { showLoading: true }){
return new Promise((resolve,reject) => {
axios.get(url,config)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url,data = {}, config = { showLoading: true }){
return new Promise((resolve,reject) => {
axios.post(url,data,config)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
```
# :-: **页面代码全览**
```
import axios from 'axios';
import {Toast} from "cube-ui";
/*请求合并只出现一次loading*/
let needLoadingRequestCount = 0
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
loading('start')/*loading加载*/
}
needLoadingRequestCount++
}
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return
needLoadingRequestCount--
if (needLoadingRequestCount === 0) {
setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/
}
}
const tryCloseLoading = () => {
if (needLoadingRequestCount === 0) {
loading('end')/*loading加载*/
}
}
/*loading加载*/
function loading (str){
let toast = Toast.$create({/*滴滴弹框*/
txt: 'Loading...',
mask: true,
time: 0
})
if(str=='start'){
toast.show()
}else if(str=='end'){
toast.hide()
}
}
/*请求拦截*/
axios.interceptors.request.use(
config => {
const token = '123412';
config.baseURL ='';
config.timeout = 5000;
if (config.showLoading) {
showFullScreenLoading()
}
config.headers['TOKEN']=token;
return config;
},
error => {
return Promise.reject(err);
}
);
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
if(response.config.showLoading){
tryHideFullScreenLoading()
}
return response;
},
error => {
Toast.$create({
txt: error.message,//错误信息
type: 'error',
time:2000,
onTimeout: () => {
if(error.config.showLoading){
tryHideFullScreenLoading()//消除loading
}
}
}).show()
return Promise.reject(error)
}
)
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function get(url, config = { showLoading: true }){
return new Promise((resolve,reject) => {
axios.get(url,config)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url,data = {}, config = { showLoading: true }){
return new Promise((resolve,reject) => {
axios.post(url,data,config)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
```
**再此感谢[woodccc](https://www.jianshu.com/p/c66adc327553)**
### :-: **其他**
[axios封装全局loading(1)](https://www.kancloud.cn/ctwee/ctwee/908764)
[axios封装全局loading(2)](https://www.kancloud.cn/ctwee/ctwee/894036)
[axios封装全局loading(3)](https://www.kancloud.cn/ctwee/ctwee/908766)
- vue
- axios封装全局loading(1)
- axios封装全局loading(2)
- axios封装全局loading(3)
- 学不动也要学,vue权限管理
- 判断前台当前页面是否需要token
- vue打包为APP(1)
- vue-cli3.0跨域
- vue-cli 3.0配置目录别名alias
- px自动转换rem
- 页面返回位置保留
- 浏览器title动态修改
- vue路由参数变化页面不刷新
- react
- 学不动也要学,react(1)
- Electron
- Electron厉害的要死(1)
- Electron厉害的要死(2)
- node
- 前后端分离
- MVC项目
- HTML
- 缓存时间机制
- 全站执行https请求
- 移动端meta
- CSS
- sticky_footer
- JS
- 子元素是否超出父元素
- iframe切换
- 获取url参数
- 回到顶部按钮
- 滚动条是否到达底部
- 移动端左右滑动div
- 移动pc相互跳转
- IE浏览器版本判断
- 调用摄像头和相册
- 抽奖概率
- cookie
- 平常小知识
- 单行文本与多行文本省略号
- display:table用法
- span标签document绑定事件失效
- 添加script标签
- 内联元素不能紧贴
- 3D旋转(transform)粗细渲染
- 全英文不换行问题
- 点击input出现蓝色边框
- wap端点击div,a,img出现阴影效果
- 华为手机使用flex布局,样式位移
- IE兼容性
- 图解
- 其他
- 未整理