Vue3のSuspenseについて興味があったので、試しに触ってみた内容をまとめます
Suspenseって?
非同期処理が解決されるまで、コンポーネントの代わりにフォールバックコンテンツをレンダリングする特別なコンポーネントです。 今まで、computedで変数を定義して、v-ifで表示制御していたのを簡単に書けるようにしたもののようです。
実際に書いてみた
親コンポネ
親コンポネでは以下のように書きます。
<template> <Suspense> <template #default> <ArticleList/> </template> <template #fallback> Loading... </template> </Suspense> </template> <script lang="ts"> import {defineComponent} from 'vue' import ArticleList from "./components/ArticleList.vue" export default defineComponent({ components: { ArticleList }, }) </script>
Suspenseは、2つのスロットを持っています。
default
最終的にレンダリングするコンテンツ
fallback
defaultに定義したコンテンツの非同期処理が完了するまでのコンテンツ
今回作ったサンプルだと、子コンポネの非同期処理が終わるまではLoadingと表示されます。
子コンポネ
非同期処理を行う子コンポネでは、以下のようにかきます。
<template> <div class="card-wrapper"> <div class="card" v-for="(article, key) in articles" :key="key"> <h1>{{ article.title }}</h1> <div>{{ article.content }}</div> </div> </div> </template> <script lang="ts"> import {defineComponent} from "vue"; export default defineComponent({ async setup() { const sampleArticles = [ {title: '記事A', content: '記事Aの内容'}, {title: '記事B', content: '記事Bの内容'}, {title: '記事C', content: '記事Cの内容'}, ] const fetchArticles = () => { return new Promise((resolve) => { setTimeout(() => { resolve(sampleArticles) }, 3000) }) }; const articles = await fetchArticles(); return { articles } } }); </script>
通常ではAPIから何らかのデータを取得して、取得したデータを表示すると思いますが 今回は、簡潔にするためにsetTimeoutで擬似的に非同期処理にしています。 ブログの記事一覧を引っ張ってくるAPIを叩いているイメージで書いています。
このように書くことで非同期処理が終わるまではLoadingと表示され、終わったら記事が表示されるようになります。
エラーが発生した際のハンドリング
非同期処理が失敗することもあると思います。
その場合は、onErrorCapturedでエラーを補足し、エラーを表示します。
onErrorCapturedは子孫コンポーネントからエラーが捕捉されるときに呼び出されるライフサイクルフックです。
<template> <div class="card-list"> <div v-if="error"> {{ error }} </div> <Suspense v-else> <template #default> <ArticleList/> </template> <template #fallback> Loading... </template> </Suspense> </div> </template> <script lang="ts"> import { defineComponent, ref, onErrorCaptured } from 'vue' import ArticleList from "./components/ArticleList.vue" export default defineComponent({ components: { ArticleList }, setup(){ const error = ref(null); onErrorCaptured((e) => { error.value = e return true; }); return { error } } }) </script>
まとめ
以上、Suspenseの使い方でした。 とてもシンプルに非同期処理の際の表示処理を書けるので便利ですね。