Go to list of users who liked
More than 5 years have passed since last update.
Vue.js 3.0 の新機能を試す。 〜 Suspense 編〜
2020年Q1リリース予定のVue.js 3.0の新機能Suspense
を試してみたのでまとめます。
かなり使い勝手が良さそうです。
(参考)
以下でVue 3.0(vue-next)の環境構築、他の新機能についてもまとめています。
Suspenseとは?
非同期処理が解決されるまでフォールバックコンテンツ(例えばLoading中アイコン)を表示してくれる特別なコンポーネントです。
いままで、v-if="loading === true"
などの状態変数を使って制御していたものを、状態変数を使わずに簡潔に書くことができます。
※ Reactには既にあるようです。https://reactjs.org/docs/concurrent-mode-suspense.html
※@kazuponさんの資料によると、まだビルドオプションで制御される機能で、不確定な部分もあるようです。
Suspenseの書き方
以下のように、<Suspense>
コンポーネントでラップして、内部の<template #default>
内に、非同期コンポーネントを、<template #fallback>
内に、その非同期コンポーネントが解決するまでに描画したいもの(フォールバックコンテンツ)を記載します。
それだけで、非同期コンポーネントの処理が解決するまでフォールバックコンテンツを描画してくれるようになります。
この場合だと、<AsyncComponents>
の非同期処理が終わるまで、loading...
という文字列を表示してくれます。
<Suspense><template#default><AsyncComponents/></template><template#fallback> loading...</template></Suspense>
Suspensのサンプル実装
サンプルとして、このGIFのように非同期処理待ちの際にLoading表示をするコンポーネントを作ります。
以下で紹介しているコードはこちらにあります。
https://github.com/kawamataryo/vue-next-ts-webpack-preview/tree/suspense-sample
1. 非同期コンポーネントの作成
まず、非同期処理を行うコンポーネントを作ります。
UserデータをAPIから取得して、User名のリストを表示することを想定しています。
ポイントはsetup()関数でasync/awaitを使いPromiseを返すところです。
これで非同期コンポーネントとして、Suspenseでの待機対象となります。
<template><ul><liv-for="(user, i) in users":key="i">{{user}}</li></ul></template><scriptlang="ts">import{defineComponent}from"vue";exportdefaultdefineComponent({asyncsetup(){// APIリクエストのモック 2000ms後にユーザー名の配列を返すconstfetchUsers=()=>{returnnewPromise<string[]>(resolve=>{setTimeout(()=>{resolve(['Jon','Bob','Nancy'])},2000)})}; // ユーザー名を取得// setup()内で読んでいるのでVue.js 2系で言うonCreated()と同じライフサイクルで実施される。constusers=awaitfetchUsers();return{users}}});</script>
2. Suspense 利用側のコンポーネント
次に、Suspense利用側のコンポーネントを書いていきます。
非同期コンポーネントを<Suspense>
の<template #default>
内に記載して、<template #fallback>
内に非同期処理が解決するまで描画したいLoading...
を記載しています。
これだけで非同期処理を待つ間はLoadingを表示するという実装が出来ます。
<template><imgsrc="./logo.png"><h1>Suspense demo</h1><Suspense><template#default><AsyncUsers/></template><template#fallback> Loading...</template></Suspense></template><scriptlang="ts">import{ref,defineComponent,onErrorCaptured,Ref}from'vue'importAsyncUsersfrom"./components/AsyncUsers.vue"exportdefaultdefineComponent({components:{AsyncUsers},setup(){}})</script>
複数の非同期コンポーネントを待つ場合
Suspenseが特に効果を発揮するのが、複数の非同期コンポーネントを待つ場合だと思います。
実装はとても簡単です。<Suspense>
内に処理を待ちたい非同期コンポーネントを列挙すればOKです。
全ての非同期コンポーネントが解決するまで、フォールバックコンテンツを描画してくれます。
<Suspense><template#default><AsyncUsers/><AsyncFoods/><AsyncAnimals/></template><template#fallback> Loading...</template></Suspense>
以下のサンプルでは、AsyncUsers, AsyncAnimalsが2000ms、AsyncFoodsが3000msの描画待ちで設定しています。
全てが解決するまでloadigを表示してくれてます。
エラーハンドリング
APIリクエストといったらエラーハンドリングが必要ですよね。Suspense
を使う場合のエラーハンドリングは、Vue3.0で新しく追加されたライフサイクルフックonErrorCaptured
で簡潔にかけます。
以下はAsyncUsers
で発生したエラーをonErrorCaptured
でキャッチして、エラーメッセージを表示する例です。
<template><divclass="container"><imgsrc="./logo.png"><h1>Suspense demo</h1><divv-if="error">{{error}}</div><Suspense><template#default><AsyncUsers></template><template#fallback> Loading...</template></Suspense></div></template><scriptlang="ts">import{defineComponent,onErrorCaptured,ref,Ref}from'vue'importAsyncUsersfrom"./components/AsyncUsers.vue"exportdefaultdefineComponent({components:{AsyncUsers,},setup(){consterror:Ref<any>=ref(null);// 非同期コンポーネントでErrorが発生した場合、このライフサイクルフックでキャッチされる。// エラーの内容を、リアクティブなエラー表示用変数の`error`に詰めているonErrorCaptured(e=>{error.value=e;returntrue;});return{error}}})</script>
AsyncUsers
であえてreject(500 Server Error")を発生させた場合はこのようになります。
終わりに
以上、Vue.js 3.0 の新機能を試す。 〜Suspense編〜 でした
状態変数を持たなくて良いのでとてもシンプルにかけますね。
早く使いたい..!!
参考
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme