最近在作vue的項目,使用了element-ui做爲ui組件庫,採用vuex進行狀態管理,與後臺的請求交互採用axios庫實現,本來作的頁面,ajax請求個數也只有三個,將等待動畫的顯示和隱藏經過mutation去控制,可是項目愈來愈大,請求也愈來愈多,可否將這個等待動畫與ajax的請求相關聯呢?vue
在element-ui中,提供了兩個方法進行調用loading組件,一個是在須要遮罩的div容器中添加v-loading指令,另外一種就是以服務形式調用:Loading.service(options),在本項目中,在加載數據時,進行全局遮罩,因此設置let loadingInstance = Loading.service({fullscreen:true})。關閉服務形式的調用:loadingInstance.close();ios
我的對攔截器的做用的理解是,在請求發送前和響應處理前,對該ajax請求進行必定的設置或者處理,方便對工程內的ajax請求進行統一處理,減小重複代碼。ajax
//請求攔截器 axios.interceptors.request.use((config) => { // 在發送請求以前作些什麼 return config; }, (error) => { // 對請求錯誤作些什麼 return Promise.reject(error); }); // 添加響應攔截器 axios.interceptors.response.use((response) => { // 對響應數據作點什麼 return response; }, (error) => { // 對響應錯誤作點什麼 return Promise.reject(error); });
有了攔截器,咱們能夠想到,在ajax請求發送前開啓loading動畫,在接收響應後關閉loading動畫。可是要對每一個ajax都開關一下loading動畫嗎?其實沒必要。只須要實現一個ajax的計數器,在個數大於0時,開啓動畫,在個數爲0的時候,關閉動畫。vuex
let loadCounter = (function(){ let count = 0; let loadingInstance; const show = () => { if(count > 0){ loadingInstance = Loading.service({fullscreen:true}); } else { if(loadingInstance) { this.$nextTick(()=>{ loadingInstance.close(): }) } } } return { increment(){ count ++; show(); }, decrement(){ count--; show(); } } })();
在具體的項目工程裏應用時,須要異步關閉loading,這是由於在有些時候,ajax請求發送的很快,尚未徹底開啓動畫時,就已經關閉動畫,這時的動畫時不能關閉的,經過異步調用的方法能夠保證動畫的關閉都是有效的,不會出現動畫關不掉的問題。$nextTick與vue組件實例生命週期相關,它指向的this必須是個vue組件,在實際應用時,能夠將全局的vue組件做爲this的指向。element-ui
//請求攔截器 axios.interceptors.request.use((config) => { loadCounter.increment(); return config; }, (error) => { loadCounter.decrement(); return Promise.reject(error); }); // 添加響應攔截器 axios.interceptors.response.use((response) => { loadCounter.decrement(); return response; }, (error) => { //異常狀況也要關閉loading loadCounter.decrement(); return Promise.reject(error); });
在實際項目中,須要對一些不須要顯示等待動效的ajax請求進行設置例外,我將這些請求添加在白名單內,在計數器中設置白名單列表,修改以下。axios
let loadCounter = (function(){ let count = 0; let loadingInstance; let whiteList = [\/query\/record/]; const show = (url) => { if(count > 0){ let valid = true; whiteList.forEach(reg=>{ if(reg.test(url)){ valid = false; } }); if(valid){ loadingInstance = Loading.service({fullscreen:true}); } } else { if(loadingInstance) { this.$nextTick(()=>{ loadingInstance.close(): }) } } } return { increment(url){ count ++; show(); }, decrement(){ count--; show(); } } })();