目录

自定义加载Loading图标效果图

基于封装axios请求的request.js实现

自定义Loading图标

集成Loading后的request.js完整代码

基于Vuex的方式实现全屏全局加载


 

官网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)//关闭

参考:

基于Vuex方式实现参考

自定义Loading图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐