在請求較多的應用中,loading是必不可少的,否則人們不是認爲程序卡了就是認爲設備卡了
普通的項目中,每次請求基本都要手動寫一下loading的出現和消失,且不說有些麻煩,而且在ajax異步的情況下,如果做不好loading同步,經常會出現loading不出現的情況,而且不同瀏覽器兼容性較差。
一.概念
在vue項目中,有了統一配置機制,可以實現對loading的配置使每次請求前自動出現loading,請求後loading消失
順表一提,本來ajax調爲同步模式挺好用的,但axios沒有同步功能
關於elementui的loading,教程在這裏:https://element.eleme.cn/2.0/#/zh-CN/component/loading
第一種方法是在需要出現loading的地方加v-loading指令,此方法在小應用中可以用,在大型應用中顯得過於繁瑣
第二種是服務方式:
最後一句話是重點,也就是說如果頁面有多個請求一起請求,如果都使用一個服務loading,很可能會出現較快結束請求的那個直接把loading關了,而請求時間長的還沒有結束請求。這點在下面設計的時候需要關注
二.實現
在main.js中,引入vue,axios,elementui
import Vue from 'vue'
import App from './App'
import router from './router'
import elementui from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
import {Loading} from 'element-ui'
//修改原型鏈,全局使用axios,這樣之後可在每個組件的methods中調用$axios命令完成數據請求
Vue.prototype.$axios=axios
// 安裝各類插件
Vue.use(elementui)
let loading;
//內存中正在請求的數量
let loadingNum=0;
function startLoading() {
if(loadingNum==0){
loading = Loading.service({
lock: true,
text: '拼命加載中...',
background:'rgba(255,255,255,0.5)',
})
}
//請求數量加1
loadingNum++;
}
function endLoading() {
//請求數量減1
loadingNum--
if(loadingNum<=0){
loading.close()
}
}
//請求數據攔截器
axios.interceptors.request.use(request => {
startLoading();
return request
}, err => {
return Promise.reject(err);
});
//接收響應攔截器
axios.interceptors.response.use(response => {
endLoading();
return response
}, err => {
endLoading();
if (err && err.response) {
switch (err.response.status) {
case 400: err.message = '請求錯誤(400)'; break;
case 401: this.$router.push('/login'); break;
case 403: err.message = '拒絕訪問(403)'; break;
case 404: err.message = '請求出錯(404)'; break;
case 408: err.message = '請求超時(408)'; break;
case 500: err.message = '服務器錯誤(500)'; break;
case 501: err.message = '服務未實現(501)'; break;
case 502: err.message = '網絡錯誤(502)'; break;
case 503: err.message = '服務不可用(503)'; break;
case 504: err.message = '網絡超時(504)'; break;
case 505: err.message = 'HTTP版本不受支持(505)'; break;
default: err.message = `連接出錯(${err.response.status})!`;
}
} else {
err.message = '連接服務器失敗!'
}
message.error(err.message);
return Promise.reject(err);
});
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
data: {
eventHub: new Vue()
}
})
因爲loading只是一個實例,所以需要加入了請求個數控制,每次請求開始加一個,請求結束減一個,當請求個數爲0時才使loading消失。
這樣配置後應用中其他組件每次調用axios請求都會自動出現消失loading。
三.解決自定義樣式問題
到這裏,每次請求的loading樣式都一模一樣了,如果有的請求需要其他的loading樣式怎麼辦呢?
利用服務中loading只有一個實例的原理,只需要在請求之前就創建出一個loading實例,因爲創建一個實例後再調用會繼續使用這個實例,loading的名字就變了
例:
在每個需要變樣式的請求前面加上這個即可