在項目中使用loading
,通常是在js中改一個變量,或者調用一個service
中的方法,好比Element Ui
中就提供了這兩種方式的loading
,這樣作有很好的擴展性。vue
BUT
,若是你作一個後臺管理項目,有一個api
就要這樣重複一下代碼,emmm...
我是接受不了,看我這個懶人是如何在vue
項目中,把自動全局的loading
封裝到axios
中的吧。ios
還有,就是我看不少朋友還在寫這樣的代碼:web
/**
* 本文簡單設想,後端返回的是比較標準的code、data、message
*/
api.http('url' , data).then(res => {
if (res.code === 200) {
// 執行成功的操做
} else {
// 錯誤提示,固然這裏只是舉例,並不是說真的alert,可是你每一個請求都要寫,多累啊!
alert(res.message)
}
})
複製代碼
vue
項目,能夠選擇用vue-cli
腳手架構建;axios
,理論上直接npm install axios
;src
目錄下建立一個utils
目錄,能夠分文件去寫一些filter
、公共方法等...;utils
目錄下建立http.js
(想怎麼命名均可以,有意思就行,大家隨意~)OK,接下來就要在http.js
中封裝一下axios
.vuex
這裏話很少說,直接上代碼了vue-cli
import axios from 'axios'
import store from '../store' // 這裏作loading會調用store
import { getToken } from '@/utils/auth' // 這個不重要,就是一個獲取tooken的
// 建立axios實例
const service = axios.create({
// api的base_url,本地配置的代理,理論上能夠不用baseURL
// baseURL: process.env.BASE_API,
timeout: 15000, // 請求超時時間
// headers 能夠經過在這裏設置,也能夠在request攔截器裏建立
// headers: {'X-Custom-Header': 'foobar'}
})
// request攔截器
service.interceptors.request.use(config => {
// !!! 這裏開始觸發 loading 效果 !!!
store.dispatch('SetLoading', true)
// 設置 token header
getToken() && (config.headers['token'] = token)
// 這個是微信登陸中須要用到 header
config.headers['deviceType'] = 'school_admin_web'
return config
},
error => {
const { response } = error
// 這裏能夠根據本身的業務作一些操做,好比說全局提示
Promise.reject(error)
})
// respone攔截器
service.interceptors.response.use(
response => {
// !!! 關閉 loading !!!
store.dispatch('SetLoading', false)
const res = response.data
if (res.code !== 200) {
// 這裏能夠作一些全局性的錯誤提示,這樣就不必在每一個請求都再寫一個else,再重複代碼提示
alert(res.message)
// 不是真的alert啊
}
return response.data
},
error => {
// !!! 關閉 loading !!!
store.dispatch('SetLoading', false)
const { response } = error
// 這裏能夠根據本身的業務作一些操做,好比說強制登出
return Promise.reject(error)
}
)
export default service
複製代碼
好了,能夠看到,其實全局的錯誤提示,在上面的代碼中有直接的體現了,這裏就很少講了,那全局的loading
的話,這裏其實調用了store
裏的SetLoading
。npm
若是您還沒用過store
,請自行學習文檔,這裏不作store
的詳細講解。axios
這裏,假想您已經熟悉store並使用store的模塊化(固然,不模塊化也無所謂,看你本身)。 假設store
目錄下有個 app module
對應的是app.js
,好了,上代碼:後端
const app = {
state: {
requestLoading: 0,
},
mutations: {
SET_LOADING: (state, boolean) => {
boolean ? ++state.requestLoading : --state.requestLoading
},
},
actions: {
SetLoading ({ commit }, boolean) {
commit('SET_LOADING', boolean)
},
},
}
export default app
複製代碼
結合對axios
的封裝代碼能夠看到,在axios
中request
攔截器中,我調用了store SetLoading
,改變了requestLoading
的數值,使其自加1;在response
攔截器中,我一樣調用了store SetLoading
,改變requestLoading
的數值,使其自減1。其總體原理,相似於垃圾回收機制,這樣作的好處是,有多個請求併發時,只有全部的請求都返回結果後,loading
效果纔會消失。api
那麼,如今焦點只處於store
下app
模塊的requestLoading
狀態,咱們拿這個判斷loading
效果便可。bash
那麼,剩餘的代碼,這裏就很少說了,
大抵是你在你的佈局層裏,定位一個陰影層的loading,經過requestLoading的狀態,來判斷顯示隱藏(相似於這樣)。
<template>
<section class="app-main">
<div class="request-loading" :class="{'request-loading-show' : requestLoading}">
<div class="loading-module"></div>
</div>
<transition name="fade-transform" mode="out-in">
<router-view/>
</transition>
</section>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AppMain',
computed: {
...mapGetters([
'requestLoading',
]),
},
}
</script>
// .request-loading-show樣式代碼這裏就不寫了,本身根據須要弄一下吧。
複製代碼
這裏也不用多說了,就是把第二部封裝好的axios import
使用就OK,這裏建議在src
下建立api
目錄,來模塊定義全部的api
,好比:
import http from '@/utils/http'
export default {
add (data) {
return http({ url: '...', data: data, method: 'post' })
},
}
// 而後在組件里正常調用便可...
複製代碼
經過以上的操做,有兩個好處,請求期間會自動顯示loading效果;當有錯誤時,全局已經作好了提示。
懶,即行爲懶,並不表明思惟懶;
懶得行爲,纔會推進思惟去成就懶...
若是有寫的不對的地方,歡迎提出~
若是您有更好的建議,歡迎留言溝通~