Element UI中使用Axios优化Loading动画

3,158 阅读2分钟

背景

最近在用Element UI + Vue 做中后台管理系统,当我们向后端发送请求时,需要给页面一个loading加载动画。Element UI给我们提供了两种调用 Loading 的方法:指令和服务。每次和后端的交互都要显示loading框的话,我们通常写在封装好的axios.js文件中以服务的形式调用。

问题分析

  • 如何解决多个请求重叠的问题?
  • 如何解决区域加载问题?

实现方法

Axios中为我们提供了请求拦截和请求响应的的接口,我们可以在axios.js中声明一个loadingInstance变量,拦截到请求之后,创建一个loading实例,请求响应之后关闭loading。

那么当多个请求重叠时会怎样呢?

假如我们同时发送两次请求,由于间隔时间极短,在创建一个loading实例之后,还未来的及关闭,loadingInstance就被重新赋值,导致我们关闭loading时只能关闭最后一个loading实例,之前创建的loading实例已经淹没在内存中无法选取,也就无从关闭它们,就会导致页面一直在loading。

所以问题的关键就是我们要关闭之前的loading实例
  • 我们可以在声明loadingInstance的同时,声明一个计数器count=0,拦截到请求之后,先对count做判断,如果count>0,就需要先关闭之前的loading实例,然后再创建新的loading实例赋值给loadingInstance,同时count++。
let loadingInstance
let count = 0;
service.interceptors.request.use(config => {
    if(count>0){
        loadingInstance.close()
    }
    count ++
    loadingInstance = Loading.service({
        target: '.content',
        text:'加载中...'
    })
    return config
}, error => {
    Promise.reject(error)
})
service.interceptors.response.use(
    response => {
        loadingInstance.close()
        count = 0
        return response
    },
)
  • 需要注意的是,以服务的方式调用的全屏 Loading 本身就是是单例的:若在前一个全屏 Loading 关闭前再次调用全屏 Loading,并不会创建一个新的 Loading 实例,而是返回现有全屏 Loading 的实例,所以不会出现重叠的情况

那么如何解决区域加载呢?

let loadingInstance = Loading.service({
    text: '请稍等',
    // 选择你要插入的节点
    target: document.querySelector('.loadingtext')
});
  • 需要注意的是虽然以服务的方式调用的全屏 Loading 本身就是是单例的,但是区域loading并不是单例的,所以如果我们要解决区域loading的重叠问题,就需要用到前面提到的办法。