前端element-ui Loading全屏全局加载动画(路由跳转和拦截请求触发)及自定义Loading图标
目录
自定义加载Loading图标效果图
图中加载图标如下
其他样式
基于封装axios请求的request.js实现
未集成loading的request.js
import axios from 'axios';
import {Message} from 'element-ui';
import store from '../vuex/store';
import qs from 'qs';
let loading = null //定义loading变量
let request = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: "user_api",
// 超时
timeout: 50000
});
request.defaults.baseURL = "user_api";
const CancelToken = axios.CancelToken;
// 防止重复请求
let removePending = (config) => {
for (let k in store.state['axiosPromiseCancel']) {
if (store.state['axiosPromiseCancel'][k].u === config.url + '&' + config.method) { //当前请求在数组中存在时执行函数体
store.state['axiosPromiseCancel'][k].f(); //执行取消操作
store.state['axiosPromiseCancel'].splice(k, 1); //把这条记录从数组中移除
}
}
};
request.interceptors.request.use(
config=>{
//只针对get方式进行序列化
if (config.method === 'get') {
config.paramsSerializer = function(params) {
return qs.stringify(params, { arrayFormat: 'repeat' })
}
}
if (config.method !== 'post') {
// 这个是 取消重点
removePending(config);
config.cancelToken = new CancelToken((cancel) => {
store.state['axiosPromiseCancel'].push({ u: config.url + '&' + config.method, f: cancel });
});
}
return config;
}
);
request.interceptors.response.use(
res => {
if (res.config.method !== 'post') {
removePending(res.config);
}
return Promise.resolve(res);
},
error => {
endLoading()
if (axios.isCancel(error)) {
// 为了终结promise链 就是实际请求 不会走到.catch(rej=>{});这样就不会触发错误提示之类了。
return new Promise(() => {});
} else {
let msg = '';
let msgCh = '';
if (error && error.response) {
switch (error.response.status) {
case 404:
msg = 'Request error, the resource was not found';
msgCh = '请求错误,未找到该资源';
break;
case 500:
msg = 'Server Error';
msgCh = '服务器错误';
break;
case 504:
msg = 'Gateway Timeout';
msgCh = '网关超时';
break;
default:
msg = error.response.data.msg;
msgCh = error.response.data.msgCh;
}
if (window.$Vue.$i18n.locale === "en") {
msgCh = msg;
}
Message({
message: msgCh,
type: 'error',
duration: 5 * 1000,
showClose : true
});
return Promise.reject();
}
}
}
);
export default request;
开始集成loading组件,在request.js 中引入 Loading 服务
import { Loading } from 'element-ui';
先了解Loading的options 参数配置项
封装loading服务调用及服务关闭
//开始 加载loading
let startLoading=()=>{
loading = Loading.service({
lock: true,
text: window.$Vue.$t('common.loading'),//加载动画的文字
background: 'rgba(0, 0, 0, 0.7)'//加载动画的背景
})
}
//结束 取消loading加载
let endLoading=()=>{
loading.close()
}
//showFullScreenLoading() 与 tryHideFullScreenLoading() 目的是合并同一页面多个请求触发loading
let needLoadingRequestCount = 0 //声明一个变量
let showFullScreenLoading=()=> {
if (needLoadingRequestCount === 0) { //当等于0时证明第一次请求 这时开启loading
startLoading()
}
needLoadingRequestCount++ //全局变量值++
}
let tryHideFullScreenLoading=()=> {
if (needLoadingRequestCount <= 0) return //小于等于0 证明没有开启loading 此时return
needLoadingRequestCount-- //正常响应后 全局变量 --
if (needLoadingRequestCount === 0) { //等于0 时证明全部加载完毕 此时结束loading 加载
endLoading()
}
}
至此,loading全屏加载动画就做好了。
下面就是如何触发。下面的栗子只针对请求拦截触发全屏全局加载动画
在request.js 中的request.interceptors.request.use
去调用方法 showFullScreenLoading() 开启loading动画。
在request.js 中的request.interceptors.
response.use
去调用方法 tryHideFullScreenLoading() 关闭loading动画。
自定义Loading图标
在src的assets的img文件夹下,存放自定义的Loading图标。
在src的assets的css文件夹下,创建一个关于自定义Loading图标的css样式文件pageLoading.css。
pageLoading.css内容如下
.el-loading-spinner{
/*这个是自己想设置的 gif 加载动图*/
background-image:url('../img/logo.png');
background-repeat: no-repeat;
background-size: 200px 120px;
height:120px;
width:100%;
background-position:center;
/*覆盖 element-ui 默认的 50% 因为此处设置了height:100%,所以不设置的话,会只显示一半,因为被top顶下去了*/
top:40%;
}
.el-loading-spinner .circular {
/*隐藏 之前 element-ui 默认的 loading 动画*/
display: none;
}
.el-loading-spinner .el-loading-text{
/*为了使得文字在loading图下面*/
margin:150px 0px;
}
在request.js 中引入自定义Loading图标的css样式文件pageLoading.css 即可生效
(这里注意,要在导入elementUI之后,再导入自己的样式,要不然会被elementUI覆盖)
import pageLoading from '../assets/css/pageLoading.css'
集成Loading后的request.js完整代码
import axios from 'axios';
import {Message,Loading} from 'element-ui';
import store from '../vuex/store';
import qs from 'qs';
let loading = null //定义loading变量
let request = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: "abc_api",
// 超时
timeout: 50000
});
import pageLoading from '../assets/css/pageLoading.css'
request.defaults.baseURL = "abc_api";
const CancelToken = axios.CancelToken;
// 防止重复请求
let removePending = (config) => {
for (let k in store.state['axiosPromiseCancel']) {
if (store.state['axiosPromiseCancel'][k].u === config.url + '&' + config.method) { //当前请求在数组中存在时执行函数体
store.state['axiosPromiseCancel'][k].f(); //执行取消操作
store.state['axiosPromiseCancel'].splice(k, 1); //把这条记录从数组中移除
}
}
};
request.interceptors.request.use(
config=>{
//只针对get方式进行序列化
if (config.method === 'get') {
config.paramsSerializer = function(params) {
return qs.stringify(params, { arrayFormat: 'repeat' })
}
}
if (config.method !== 'post') {
// 这个是 取消重点
removePending(config);
config.cancelToken = new CancelToken((cancel) => {
store.state['axiosPromiseCancel'].push({ u: config.url + '&' + config.method, f: cancel });
});
}
showFullScreenLoading()
return config;
}
);
request.interceptors.response.use(
res => {
if (res.config.method !== 'post') {
removePending(res.config);
}
tryHideFullScreenLoading()
return Promise.resolve(res);
},
error => {
endLoading()
if (axios.isCancel(error)) {
// 为了终结promise链 就是实际请求 不会走到.catch(rej=>{});这样就不会触发错误提示之类了。
return new Promise(() => {});
} else {
let msg = '';
let msgCh = '';
if (error && error.response) {
switch (error.response.status) {
case 404:
msg = 'Request error, the resource was not found';
msgCh = '请求错误,未找到该资源';
break;
case 500:
msg = 'Server Error';
msgCh = '服务器错误';
break;
case 504:
msg = 'Gateway Timeout';
msgCh = '网关超时';
break;
default:
msg = error.response.data.msg;
msgCh = error.response.data.msgCh;
}
if (window.$Vue.$i18n.locale === "en") {
msgCh = msg;
}
Message({
message: msgCh,
type: 'error',
duration: 5 * 1000,
showClose : true
});
return Promise.reject();
}
}
}
);
//开始 加载loading
let startLoading=()=>{
loading = Loading.service({
lock: true,
text: window.$Vue.$t('common.loading'),//加载动画的文字
background: 'rgba(0, 0, 0, 0.7)'//加载动画的背景
})
}
//结束 取消loading加载
let endLoading=()=>{
loading.close()
}
//showFullScreenLoading() 与 tryHideFullScreenLoading() 目的是合并同一页面多个请求触发loading
let needLoadingRequestCount = 0 //声明一个变量
let showFullScreenLoading=()=> {
if (needLoadingRequestCount === 0) { //当等于0时证明第一次请求 这时开启loading
startLoading()
}
needLoadingRequestCount++ //全局变量值++
}
let tryHideFullScreenLoading=()=> {
if (needLoadingRequestCount <= 0) return //小于等于0 证明没有开启loading 此时return
needLoadingRequestCount-- //正常响应后 全局变量 --
if (needLoadingRequestCount === 0) { //等于0 时证明全部加载完毕 此时结束loading 加载
endLoading()
}
}
export default request;
基于Vuex的方式实现全屏全局加载
1、先了解 vuex是用来干嘛的?
其实就是存储配置信息及数据的,如定义好的方法,常量等等。
2、在store.js文件中以服务的方式调用,引入 Loading 服务
import { Loading } from 'element-ui';
3、在 state(Vuex集中变量存储仓库)中新增一个变量为options
const state={
options:{
lock: true,
text: '加载中,请稍后',//加载动画的文字
spinner: 'el-icon-loading',//加载动画的图标
background: 'rgba(0, 0, 0, 0.7)'//加载动画的背景
},
}
4、在你的mutations
中 新建你的全局方法调用这个服务
const mutations={
showLoading(state,val){
let loadingInstance = Loading.service(state.options);
val? Loading.service(state.options) : loadingInstance.close() //这里判断调用方法时候的参数值,打开服务的时候传true,关闭服务的时候传false
},
}
以上 options 及 服务调用的方法 都定义好了之后,就可以使用他们了。
打开你的路由跳转router文件,关于路由跳转拦截我这里放在main.js文件中。
引入Vuex
import store from '../vuex/store'
//前置守卫
router.beforeEach((to, from, next) => {
if(login){//这里写的假判断,一般在你的路由守卫中,什么时候调用next(),什么时候调用你的打开服务方法
vuex.commit('showLoading',true);
next()
}else{
next({
path: '/'
})
}
})
//后置钩子
router.afterEach(() =>{
vuex.commit('showLoading',false)
})
至此,页面跳转时的全屏加载动画就做好了。
请求的时候使用同样的方式去调用这两个方法;
发起请求的时候,在你的axios.interceptors.request.use
的 onFulfilled中 去调用方法传true,在axios.interceptors.response.use
调用方法传false
vuex.commit('showLoading',true);//开启
vuex.commit('showLoading',false)//关闭
参考:
更多推荐
所有评论(0)