目錄
一、概述
VueWait是一個復雜的裝載器和進度管理組件,常用於Vue、Vuex和Nuxt。VueWait可以幫助管理頁面上的多個加載狀態,狀態之間不會有任何沖突。
實現思路:通過管理具有多個加載狀態的數組(或者Vuex存儲),讓內置加載程序組件偵聽注冊的加載程序,並立即進入加載狀態。
二、引入VueWait組件
第一步:安裝
> npm i vue-wait
第二步:在main.js中全局注冊
import VueWait from 'vue-wait'
Vue.use(VueWait)
new Vue({
wait: new VueWait()
})
三、常見應用
/**
* Vuex模塊
*/
import api from '@/api/demo/index';
import axios from 'axios';
export const namespace = 'demo/index';
export const actions = {
DEMOAC: 'demoac'
};
export default {
namespaced: true,
state,
mutations,
actions: {
[actions.DEMOAC](context) {
return axios.post('');
// return不能省略, 必須返回一個Promise對象, 否則該例中的加載器無效
}
}
};
<template>
<el-table v-loading="$wait.is('jpf-loading')"></el-table>
</template>
<script>
// 引入vue-wait
import { mapWaitingActions } from 'vue-wait';
// 引入store的命名空間
import { namespace, actions } from '@/store/index';
export default{
mounted(){
this.getList();
},
methods: {
// namespace為Vuex模塊名稱, 不能隨便寫
// 如果vuex不區分模塊, 可省略
...mapWaitingActions(namespace, {
getList: {
// 屬性值為字符串, 指向Vuex模塊中actions里面的方法
action: actions.demoac,
// 自定義加載器名稱
loader: 'jpf-loading'
},
getMsg: {
// ...
}
});
}
};
</script>
注意,如果VueWait是全局配置的,則啟動的加載器可在任意組件使用。
四、拓展
拓展1:VueWait的默認屬性配置
new Vue({
render: h => h(App),
wait: new VueWait({
// 默認值如下
useVuex: false, // 使用Vuex管理等待狀態
vuexModuleName: 'wait', // 默認的Vuex模塊名稱
registerComponent: true, // 注冊v-wait組件
componentName: 'v-wait', // <v-wait>組件名稱, 可自定義
registerDirective: true, // 注冊v-wait指令
directiveName: 'wait' // <span v-wait />偽指令名稱, 可自定義
})
}).$mount('#app')
拓展2:使用Vuex管理等待狀態
全局注冊時,將useVuex配置項設置為true,即可使用Vuex管理等待狀態。
import VueWait from 'vue-wait'
Vue.use(VueWait)
new Vue({
wait: new VueWait({
useVuex: true,
vuexModuleName: 'vuex-example-module' // Vuex模塊名稱, 可選的, 默認為'wait'
})
})
拓展3:VueWait選項
可以使用如下配置項,自定義VueWait的行為。
選項名稱 | 類型 | 默認 | 描述 |
---|---|---|---|
accessorName | String | "$wait" | 設置訪問器名稱,可更改 |
useVuex | Boolean | false | 是否啟用與Vuex組件的集成,若啟用則v-wait組件和指令禁用 |
vuexModuleName | String | "wait" | Vuex模塊名稱 |
registerComponent | Boolean | true | 注冊v-wait組件 |
componentName | String | "v-wait" | 更改v-wait組件名稱 |
registerDirective | Boolean | true | 注冊v-wait指令 |
directiveName | String | "v-wait" | 更改v-wait指令名稱 |
拓展4:全局模板屬性
VueWait提供了一些全局模板屬性,可通過$wait訪問,功能如下所示。
.any
任意加載器啟動,返回true,沒有任何加載器啟動時,返回false。
<template>
<div v-if="$wait.any">加載中...</div>
<button @click="$wait.start('loader')">啟動加載器</button>
<button @click="$wait.end('loader')">關閉加載器</button>
</template>
.is(loader String | Matcher) / .waiting(loader String | Matcher)
啟動指定加載器時,返回true,否則返回false。注意,可以使用matcher匹配器使代碼更靈活。
<template>
<div v-if="$wait.is('loader')">加載中...</div>
<button @click="$wait.start('loader')">啟動加載器</button>
<button @click="$wait.end('loader')">關閉加載器</button>
</template>
<template>
<!-- 使用matcher匹配器 -->
<div v-if="$wait.is('loader.*')">加載中......</div>
</template>
.is(loader Array<String | Matcher>) 或 .waiting(loader Array<String | Matcher>)
數組中包含的任意加載器啟動,返回true,否則返回false。注意,可以使用matcher匹配器使代碼更靈活。
<template>
<div v-if="$wait.is(['loader1', 'loader2'])">sdfd</div>
</template>
.start(loader String)、.end(loader String)
啟動/關閉指定加載器。
<template>
<div>
<button @click="$wait.start('jpf')">啟動加載器</button>
<button @click="$wait.end('jpf')">關閉加載器</button>
<div v-if="$wait.is('jpf')">loading......</div>
</div>
</template>
.progress(loader String, current [, total = 100])
設置指定加載器的進度。current表示當前進度,totle表示總量。
<template>
<div>
<progress min="0" max="100" :value="$wait.percent('downloading')"/>
<button @click="$wait.progress('downloading', 10)">Set progress to 10</button>
<button @click="$wait.progress('downloading', 50)">Set progress to 50</button>
<button @click="$wait.progress('downloading', 50, 200)">
Set progress to 50 of 200 (25%)
</button>
</div>
</template>
.percent(loader String)
返回指定加載器的百分比。
<template>
<progress min="0" max="100" :value="$wait.percent('downloading')"/>
</template>
拓展5:指令
使用指令可以使模板更簡潔,如下是一些指令的用法。
v-wait:visible="'loader String'"
指定加載器啟動,返回true,關閉返回false。
<template>
<div>
<button @click="$wait.start('jpf')">啟動加載器</button>
<button @click="$wait.end('jpf')">關閉加載器</button>
<div v-wait:visible="'jpf'">加載中......</div>
</div>
</template>
v-wait:hidden="'loader String'" 或 v-wait:visible.not="'loader String'"
指定加載器關閉,返回true,啟動返回false。
<template>
<div>
<button @click="$wait.start('jpf')">啟動加載器</button>
<button @click="$wait.end('jpf')">關閉加載器</button>
<div v-wait:hidden="'jpf'">加載中......</div>
</div>
</template>
v-wait:disabled="'loader String'"
指定加載器啟動,則給當前元素標簽添加disabled特性,否則移除disabled特性。
<template>
<div>
<button @click="$wait.start('jpf')">啟動加載器</button>
<button @click="$wait.end('jpf')">關閉加載器</button>
<input v-wait:disabled="'jpf'" placeholder="測試" />
<!-- 使用*匹配器 -->
<input v-wait:disabled="'*'" placeholder="測試" />
</div>
</template>
v-wait:enabled="'loader String'" 或 v-wait:disabled.not="'loader String'"
指定加載器啟動,則給當前元素標簽移除disabled特性,否則添加disabled特性。
<template>
<div>
<button @click="$wait.start('jpf')">啟動加載器</button>
<button @click="$wait.end('jpf')">關閉加載器</button>
<input v-wait:enabled="'jpf'" placeholder="測試" />
<input v-wait:disabled.not="'jpf'" placeholder="測試" />
</div>
</template>
v-wait:click.start="'loader String'"、v-wait:click.end="'loader String'"
單擊啟動/關閉指定加載器。
<template>
<div>
<button v-wait:click.start="'jpf'">啟動加載器</button>
<button v-wait:click.end="'jpf'">關閉加載器</button>
<input v-wait:disabled="'jpf'" placeholder="測試" />
</div>
</template>
v-wait:toggle="'loader String'"
單擊時切換指定加載器的狀態。
<template>
<div>
<button v-wait:toggle="'jpf'">切換加載器</button>
<input v-wait:disabled="'jpf'" placeholder="測試" />
</div>
</template>
v-wait:click.progress="['loader String', 80]"
單擊時設置指定加載器的進度。
<template>
<div>
<progress min="0" max="100" :value="$wait.percent('downloading')" />
<button v-wait:click.progress="['downloading', 80]">設置加載進度</button>
</div>
</template>
拓展6:action映射器和getter映射器
VueWait提供了action映射器和getter映射器來配合Vuex使用。action映射器有兩個參數。其一為vuex的模塊名,如果vuex沒有區分模塊,可省略,其二為wait配置。
假設有一個名為getList的異步操作,它將調用映射的方法,並在解析動作時啟動加載器。
/**
* vuex代碼
*/
actions: {
getList() {
return axios.post(postApi);
}
}
// return不能省略, 必須返回一個Promise對象, 否則action映射器中設置的加載器無效
<template>
<div>
<button @click="getList">Set progress to 10</button>
<p v-if="$wait.is('jpfLoader')">加載中.....</p>
<p v-if="$wait.is('demoloader')">加載中.....</p>
</div>
</template>
<script>
import { mapWaitingActions, mapWaitingGetters } from 'vue-wait'
export default {
computed: {
...mapWaitingGetters({
demoloader: 'jpfLoader'
})
// mapWaitingGetters將加載器映射到自定義變量名
},
methods: {
...mapWaitingActions({
getList: 'jpfLoader'
})
// key值表示vuex中action方法名, 不能自定義
// value值為自定義加載器(不用mapWaitingGetters映射, 也可以直接使用)
}
}
</script>
還可以將vuex的action操作映射到自定義方法,並自定義加載器名稱,代碼如下所示。
<template>
<div>
<button @click="fn">測試</button>
<p v-if="$wait.is('jpfLoader')">加載中.....</p>
</div>
</template>
<script>
import { mapWaitingActions } from 'vue-wait';
export default{
methods: {
...mapWaitingActions({
fn: {
action: 'getList',
loader: 'jpfLoader'
}
})
}
}
</script>
action映射器的第二個參數也可以是數組,如下代碼所示。
<template>
<div>
<button @click="demo">Set progress to 10</button>
<p>{{$wait.is('demoloader')}}</p>
</div>
</template>
<script>
import { mapWaitingActions } from 'vue-wait'
export default {
methods: {
...mapWaitingActions([
// 將vuex方法映射到自定義方法名, 並設置自定義加載器名
{ method: 'demo1', action: 'getList1', loader: 'demoloader1' },
{ method: 'demo2', action: 'getList2', loader: 'demoloader2' }
])
}
}
</script>
拓展7:waitFor(loader String,func Function[,forceSync = false])
waitFor可以用來包裝函數。第一個參數為加載器,調用包裝函數時啟動加載器。第二個參數為原始函數,原始函數加載完成后關閉加載器。
默認情況下,waitFor返回的是異步函數。如果需要返回同步函數,只須將最后一個參數設置為true。注意,最后一個參數設置為true后,加載器會失效。
<template>
<div>
<button @click="fetchDataFromApi">Set progress to 10</button>
<p>{{$wait.is('demoloader')}}</p>
</div>
</template>
<script>
import { waitFor } from 'vue-wait'
export default {
methods: {
fetchDataFromApi: waitFor('demoloader', () => {
return new Promise(resolve => setTimeout(resolve, 500));
// return 不能省略, 且必須返回Promise對象, 否則加載器無效
})
}
}
</script>
拓展8:v-wait組件
啟用
VueWait默認啟用v-wait組件,如下代碼所示。
import VueWait from 'vue-wait'
Vue.use(VueWait)
new Vue({
wait: new VueWait({
registerComponent: true // 默認值, 啟動v-wait組件
})
})
如果將配置項registerComponent設置為false,則禁用v-wait組件,此時可以通過手動導入的方式繼續使用該組件。
new Vue({
wait: new VueWait({
registerComponent: false// 禁用v-wait組件
})
})
<script>
// 手動導入v-wait組件
import vLoading from 'vue-wait/src/components/v-wait.vue'
export default {
components: {
'v-wait': vLoading
}
}
</script>
應用
<template>
<div>
<!-- loader是加載器名稱, 對應v-wait標簽的for特性 -->
<button @click="$wait.start('loader')">啟動加載器</button>
<button @click="$wait.end('loader')">關閉加載器</button>
<v-wait for="loader">
<!-- 插槽名稱不能更改, template標簽可以換成其它 -->
<template slot="waiting">
<div>
啟動加載器時展示
</div>
</template>
<div>關閉加載器時顯示</div>
</v-wait>
</div>
</template>
<!-- 按鈕點擊后加載狀態設置 -->
<template>
<button
:disabled='$wait.is("loader")'
@click="$wait.start('loader')"
>
<v-wait for='loader'>
<template slot='waiting'>加載中...</template>
按鈕
</v-wait>
</button>
</template>
拓展9:v-wait組件和可以與其它組件庫搭配使用
只須將slot='waiting'添加到對應組件,vue即可處理其余工作。
import { OrbitSpinner } from 'epic-spinners';
Vue.component('orbit-spinner', OrbitSpinner);
<v-wait for='something to load'>
<orbit-spinner
slot='waiting'
:animation-duration="1500"
:size="64"
:color="'#ff1d5e'"
/>
</v-wait>
還可以使用其它的組件庫:https://github.com/vuejs/awesome-vue#loader