背景
最近在用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 loadingInstancelet 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的重叠问题,就需要用到前面提到的办法。