はじめに
先日開催されたHTML5勉強会にてkoba04氏のReact Suspenseのデモを拝聴した際に、同じような挙動をvue.jsで作れないかと思い土日で実装してみました。
※Suspenseの実装は全く追ってません。見た目上同じUXを得られる挙動をゴールとして作ってみたものとなります。
vue-wait-component
ネーミングは適当です。
挙動としては利用者が任意でローディング演出を出すタイミングを制御できるコンポーネントです。
利用シーンは通信環境の良い(速い)ユーザーにはローディング演出を省き、悪い(遅い)ユーザーにはローディング演出を出す、といった想定です。
昨日弊社で開催したLT Loversでも発表させていただきました!
使い方
$ npm install vue-wait-component
or
$ yarn add vue-wait-component
ライブラリをパッケージ管理ツールから取得し、利用したいvueコンポーネントのscriptタグ内で読み込んでcomponentsに登録します。
<script>
import { WaitList, WaitImg } from 'vue-wait-component'
export default {
components: { WaitList, WaitImg }
}
</script>
これでカスタムタグとして利用できるようになりました。
WaitList
propsにPromiseオブジェクトを与えてresolveが返ったタイミングでslotのloadingとloadedを切り替えます。
propsのwaitにはloadingを出すまでの遅延ミリ秒を指定し、その遅延より早くPromiseオブジェクトのresolveが返ればloadingが表示される前にloadedが表示されます。
実装は以下のようになります。
<wait-list
:wait=200
:promiseMethod="sample()">
<p slot="loading">loading</p>
<div slot="loaded">
<li v-for="val in data" :key="val.text">
<p>{{ val.text }}</p>
</li>
</div>
</wait-list>
...
<script>
...
methods: {
sample() {
return new Promise(resolve => {
axios.get('/user?ID=12345')
.then(response => {
resolve(response);
})
.catch(error => {
reject(error);
});
}).then(response => {
this.data = response;
});
},
},
...
</script>
この例ではaxiosのレスポンスが200ms以上かかった場合にだけloading演出を出す実装になっています。
axiosのオブジェクトをそのままreturnしても良いですが、Cacheなどを利用する際はこのようにPromiseオブジェクトに内包し、すでCache済みであればそれをresolveするようにしてあげると良いかと思います。もちろんVuexのactionで同じような実装をしても良いです。
WaitImg
こちらのコンポーネントは事前にsrcに設定されている画像をfetchして、resolveが返ったタイミングで画像を表示させる仕様になっています。
低速回線環境において、画像が断片的に表示されていくのを防ぐのと、画像取得に時間がかかる場合はローディング演出を出すようにする、などを利用シーンとしています。
実装は以下のようになります。
<wait-img
src="https://~~~.com/~~~.jpg"
alt="test"
:width=300
:wait=100>
<p slot="loading">loading</p>
</wait-img>
こちらはimgタグとあまり変わらないのではないでしょうか。WiatListと同様にwaitでローディング演出を出すタイミングを遅延させることができます。
遅延の演出はslotのloadingに設定してください。
GitHub.ioにDEMOページを用意していますのでよろしければ体験してみてください。React Suspenseで実現していたものをVueで再現できたかと思います。(細かくは違うかもしれませんがあくまでもUXとして)
弊社アイスタイルでは新規案件やリプレース案件でVue.jsを採用することが多くなっています。
一緒にフロントエンドを開発・改善してくださるメンバーを随時募集しています!