需求是實現在每次后台請求數據時顯示加載動畫,請求完成動畫消失。
實現方法可以借助之前的axios攔截器,在請求前顯示動畫,請求結束清除動畫。
axios.interceptors.request.use( (config) => { // 所有請求之前都要執行的操作 //根據接口傳入參數顯示加載動畫 showFullScreenLoading(); return config; }, function (err) { return Promise.reject(err); } ); //http response 攔截器 axios.interceptors.response.use((response) => { // 所有請求完成后都要執行的操作 //暫停加載動畫 tryHideFullScreenLoading(); return response; }, function (err) { if (err.response) { switch (err.response.status) { case 401: // 返回 401 清除token信息並跳轉到登錄頁面 store.dispatch("logout"); router.replace({ path: 'login', query: { redirect: router.history.current.fullPath } }); } } return Promise.reject(err); });
因為我使用的是CDN引入的ElementUI,所以loading動畫實現方式為:
則elementUI顯示loading加載動畫方法為:
let loading;
function startLoading() { loading = Vue.prototype.$loading({ lock: true, text: "加載中...", background: "rgba(0, 0, 0, 0.8)" }); }
清除loading加載動畫方法為:
function endLoading() { loading.close(); }
但是需要考慮一個問題,可能同時發起多個請求,而我們顯示動畫是一次性的,即等當前所有請求完畢后在清除動畫。
//聲明一個對象用於存儲請求個數 let needLoadingRequestCount = 0; function showFullScreenLoading() { if (needLoadingRequestCount === 0) { startLoading(); } needLoadingRequestCount++; }; function tryHideFullScreenLoading() { if (needLoadingRequestCount <= 0) return; needLoadingRequestCount--; if (needLoadingRequestCount === 0) { endLoading(); } };
目前這個加載動畫是全屏 Loading,我的項目是屬於后台管理系統,頁面頭部和菜單欄是不會變化的,所以只需要在主界面里面做動畫加載即可。設置的方法是在loading配置參數中添加target來控制。
function startLoading() { loading = Vue.prototype.$loading({ lock: true, text: "加載中...", background: "rgba(0, 0, 0, 0.8)", target: document.querySelector('.loadingtext')//設置加載動畫區域 }); }
至此,還存在一個優化問題,當請求響應很快時,頁面會出現閃屏現象,其實是loading加載動畫顯示后又很快的被清除,就會出現閃屏現象。解決思路是在加載動畫中做個延遲如果響應超過某個時間段再顯示loading否則就不出現。目前還沒想到比較好的解決方法。