序
在后台管理项目中接口的请求响应速度取决于很多因素,如网络、带宽、同时发起的请求数量===,无法将请求结果及时响应的页面上,而我们又需要告诉用户,数据已经在加载了,你需要先等一等,喝杯茶。这个时候就需要 loading
了 ,但是一个项目里又不仅仅是只有一个请求,每个都写一遍 loading ? 可能真的有人这样干,但是我懒啊!我就想写一个 全局loading
需要他的时候他出来,不需要的时候他离开?,他来了----
全局loading
涉及知识 vue(一点点---)、vuex、axios拦截器、vue-router拦截器
新建一个 loading.js 文件( ps:只要你找的到放到哪里都行!瞎说的?)
// 引入 store 也就是 vuex
import store from '../store/index'
// 声明一个用于计数的变量
let loadingNum = 0
const startLoading = () =>{
// 在首页发起的请求不进行累加 (这个判断是因为项目内又一个首页大屏不需要这个全局 loading,无的话可以直接去除!)
if (global.location.hash !== '#/home') {
loadingNum ++
store.commit('setChangeLoading', true)
}
}
const endLoading = () =>{
// 此处同上
if (global.location.hash !== '#/home') {
loadingNum --
// 这个纯属是防止某些极端情况下变量减成负数(当然此处可以优化 但是我觉得这样写意图更明显!)
loadingNum = loadingNum < 0 ? 0 : loadingNum
if (!loadingNum) {
store.commit('setChangeLoading', false)
}
}
}
// 重置函数
const resetLoading = (store) =>{
// 每次路由变化 重置loading
loadingNum = 0
store.commit('setChangeLoading', false)
}
// 导出函数
export default {
startLoading,
endLoading,
resetLoading
}
vuex 配置
既然是全局的肯定带有一个地方存状态不是,项目里有vuex不用白不用啊!什么 没有怎么办 localStorage,sessionStorage
也是一样的无非是存个全局变量。
// state
state: {
loadingState: false
},
// 在 mutations 中写一个与上边同名的 setChangeLoading 函数
mutations: {
setChangeLoading(state, data) {
state.loadingState = data
}
}
vue-router 路由拦截器配置
这里主要是为了页面切换重置 全局loading
的状态, 路由在变化以后,用户其实是不在关心数据有没有响应完毕,假如用户在上一个路由加载的数据比较多,数据响应时间比较长,在用户切换路由时数据并未加载完毕,又发起了新的请求。那么全局loading
其实是会受到历史路由的影响的。
// 记得引入 loading.js
import loading from '../utils/loading'
// 创建一个路由 全局前置守卫
router.beforeEach((to, from, next) => {
// 记得引入 loading.js
// 也不关心他三个参数是干啥的 反正路由变了 我就重置 全局loading
loading.resetLoading()
})
axios 拦截器配置
这个其实也没啥说的,如果理解拦截器就应该知道要做啥了,1. 发起请求加载 全局loading
2. 请求加载完毕及发生错误关闭全局loading
// 这个文件是你封装的 axios 文件内
// 1. 引入loading、store 不会有人问为啥要引入吧?
import loading from '../utils/loading'
import store from '../store'
// 请求拦截器
service.interceptors.request.use(async (config) => {
// 开始请求加载
loading.startLoading()
return config
}, err => {
// 发生错误清除
loading.endLoading()
return Promise.reject(err)
})
// 响应拦截器
service.interceptors.response.use(response => {
// 加载完毕清除
loading.endLoading()
}, err => {
// 发生错误清除
loading.endLoading()
return Promise.reject(handleError(err));
});
那我要是想某些请求不加载全局loading呢? 咱都有拦截器了这不是很简单?
// 在此数组中不加载全局loading 根据 url匹配
const loadingWhitelist = [
'/place/xxx/12121'
]
// 判断是否包含指定url
function isLoadingWhite (url) {
//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果没有找到匹配的字符串则返回 -1。
return loadingWhitelist.some(item => { return url.indexOf(item) === -1})
}
// 请求拦截器
service.interceptors.request.use(async (config) => {
// 判断加载 全局loading (config里包含了配置信息及请求信息, 具体可以打印看一下)
if (isLoadingWhite(config.url)) { loading.startLoading() }
return config
}, err => {
loading.endLoading()
return Promise.reject(err)
})
在app.vue内使用
<template>
<div id="app">
<router-view/>
<el-col class="loading"
v-show="$store.state.loadingState"
element-loading-text="正在加载中..."
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.5)"
v-loading="$store.state.loadingState">
</el-col>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style lang="stylus">
#app{
.loading {
position absolute
top: 0
left 0
width 100%
height 100vh
z-index 999999
background rgba(94, 171, 198, 0.1)
}
}
</style>
其实我是放在layout主体布局文件内使用的!
结尾
任何东西都没有百分之百适用于所有人,写这个更多是为了写 全局loading
的实现思路,所以照搬可能会有问题,如要使用还是要结合自己的理解。谢谢!
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!