はじめに
先日開催された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を採用することが多くなっています。
一緒にフロントエンドを開発・改善してくださるメンバーを随時募集しています!

 
																				 
																				