Vue3の非同期コンポーネントを使ってみる
皆様、いかがお過ごしでしょうか。
今回はVue3の非同期コンポーネントがどんなものか使いながら理解していきたいと思います。
インストール
筆者の環境は以下の通りです。
$ node -v
v22.5.1
$ npm -v
10.8.2
Viteで開発環境を構築していきます。ESLintとPrettierのみ入れます。
$ npm create vue@lateset
> npx
> create-vue
Vue.js - The Progressive JavaScript Framework
✔ Project name: … asyncComponent
✔ Package name: … asynccomponent
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
? Add Vue DevTools 7 extension for debugging? (experimental) › No / Yes
$ cd asyncComponent
$ npm install
$ npm run format
$ npm run dev
生成されたディレクトリやファイルで今回不要な以下を削除します。
src/components
の中のディレクトリとファイル一式src/App.vue
の内容
初期表示画面の準備
以下の画像のような、海外の著名人の名言をボタンで切り替えて表示できるような画面を作ります。
▼初期表示画面
コードは以下の通りです。
<!-- src/App.vue -->
<script setup>
import PersonOne from './components/PersonOne.vue'
import PersonTwo from './components/PersonTwo.vue'
import PersonThree from './components/PersonThree.vue'
import { ref } from 'vue'
const pageNum = ref(1)
</script>
<template>
<h1>海外の著名人の名言集</h1>
<PersonOne v-if="pageNum === 1" />
<PersonTwo v-if="pageNum === 2" />
<PersonThree v-if="pageNum === 3" />
<button @click="pageNum = 1">1</button>
<button @click="pageNum = 2">2</button>
<button @click="pageNum = 3">3</button>
</template>
<!-- src/components/PersonOne.vue -->
<template>
<p>
1. Things may come to those who wait, but only the things left by those who hustle.<br />(Abraham
Lincoln)
</p>
</template>
<!-- src/components/PersonTwo.vue -->
<template>
<p>
2. All your dreams can come true if you have the courage to pursue them. <br />(Walt Disney)
</p>
</template>
<!-- src/components/PersonThree.vue -->
<template>
<p>3. Action is the foundational key to all success. <br />(Pablo Picasso)</p>
</template>
基本的な使い方
参考:非同期コンポーネント
準備ができた状態で、ブラウザをリロードして、デベロッパーツールの「Network」タブで確認すると、全ての名言コンポーネントが一括でロードされています。
▼リロード後の初期表示画面
本来初期画面の表示時にPersonTwo.vue
とPersonThree.vue
は不要です。これらはそれぞれのボタンをクリックされたタイミングでロードされて表示されればいいですよね。
そこで非同期コンポーネントを使って以下のように書き替えます。
<!-- src/App.vue -->
<script setup>
import PersonOne from './components/PersonOne.vue'
import { defineAsyncComponent } from 'vue'
import { ref } from 'vue'
const PersonTwo = defineAsyncComponent(() => import('./components/PersonTwo.vue'))
const PersonThree = defineAsyncComponent(() => import('./components/PersonThree.vue'))
const pageNum = ref(1)
</script>
<template>
<h1>海外の著名人の名言集</h1>
<PersonOne v-if="pageNum === 1" />
<PersonTwo v-if="pageNum === 2" />
<PersonThree v-if="pageNum === 3" />
<button @click="pageNum = 1">1</button>
<button @click="pageNum = 2">2</button>
<button @click="pageNum = 3">3</button>
</template>
再度ブラウザをリロードして、デベロッパーツールの「Network」タブで確認すると、PersonOne
コンポーネントのみロードされています。
▼再リロード後の初期表示画面
ボタンをクリックして名言2を表示させると、そのタイミングでPersonTwoコンポーネントがロードされていることが分かります。名言3も同じくです。
▼ボタン2をクリック
▼ボタン3をクリック
ローディングとエラーの状態
参考:非同期コンポーネント
ローディングの状態
例えば、通信環境が悪い状態だと、ボタン1からボタン2に切り替えたタイミングで何も表示されない状態になってしまいます。「Now Loading…」等の文言を表示できたら分かりやすいですよね。
デベロッパーツールの「Network」タブの「No throttling」を3GやSlow4Gに変更すると通信速度を遅い状態を検証できます。以下の記事を参考にぜひ試してみてください。不安定な通信環境でWebサイトがどう表示されるかをシミュレートする方法 | ワードプレステーマTCD
▼通信環境が悪い状態でPersonTwo
コンポーネントがロードされるまで何も表示されない
非同期コンポーネントの読み込み中に使用するローディングコンポーネントを定義します。
<!-- src/components/NowLoading.vue -->
<template>
<p>Now Loading...</p>
</template>
<!-- src/App.vue -->
<script setup>
import PersonOne from './components/PersonOne.vue'
import NowLoading from './components/NowLoading.vue'
import { defineAsyncComponent } from 'vue'
import { ref } from 'vue'
const PersonTwo = defineAsyncComponent({
loader: () => import('./components/PersonTwo.vue'),
delay: 200,
loadingComponent: NowLoading,
})
const PersonThree = defineAsyncComponent({
loader: () => import('./components/PersonThree.vue'),
delay: 200,
loadingComponent: NowLoading,
})
const pageNum = ref(1)
</script>
<template>
<h1>海外の著名人の名言集</h1>
<PersonOne v-if="pageNum === 1" />
<PersonTwo v-if="pageNum === 2" />
<PersonThree v-if="pageNum === 3" />
<button @click="pageNum = 1">1</button>
<button @click="pageNum = 2">2</button>
<button @click="pageNum = 3">3</button>
</template>
通信状態が悪い状態でボタン2をクリックすると、指定したNowLoading
コンポーネントが表示されています。その後少ししてPersonTwo
コンポーネントが表示されます。
ローディングコンポーネントが表示されるまでに、デフォルトで 200msの遅延を設定しています。これは、高速なネットワークではローディング状態が短く、置き換えが速すぎて、ちらつきのように見えてしまうからです。
▼NowLoading
コンポーネントが表示される
エラーの状態
ボタン2をクリックする直前で例えば通信が切断された場合にエラーのコンポーネントを表示することもできます。
<!-- src/components/ErrorComp.vue -->
<template>
<p>Error! Something Wrong.</p>
</template>
<!-- src/App.vue -->
<script setup>
import PersonOne from './components/PersonOne.vue'
import NowLoading from './components/NowLoading.vue'
import ErrorComp from './components/ErrorComp.vue'
import { defineAsyncComponent } from 'vue'
import { ref } from 'vue'
const PersonTwo = defineAsyncComponent({
loader: () => import('./components/PersonTwo.vue'),
loadingComponent: NowLoading,
errorComponent: ErrorComp,
timeout: 3000
})
const PersonThree = defineAsyncComponent({
loader: () => import('./components/PersonThree.vue'),
loadingComponent: NowLoading,
errorComponent: ErrorComp,
timeout: 3000
})
const pageNum = ref(1)
</script>
<template>
<h1>海外の著名人の名言集</h1>
<PersonOne v-if="pageNum === 1" />
<PersonTwo v-if="pageNum === 2" />
<PersonThree v-if="pageNum === 3" />
<button @click="pageNum = 1">1</button>
<button @click="pageNum = 2">2</button>
<button @click="pageNum = 3">3</button>
</template>
リクエストが長すぎる場合にエラーコンポーネントを表示するために、timeout を指定することもできます。
▼ボタン2をクリックする直前でオフラインになった場合にErrorComp
コンポーネントが表示される
終わりに
いかがでしたでしょうか。
非同期コンポーネントを利用することで、初期表示時のパフォーマンスが向上する可能性があると感じました。
また、読み込み中に「読み込んでいますよ~」と表示することで、ユーザーフレンドリーになるとも思いました。
今後も引き続き、Vue3を使って気づいた点をまとめていければと思います。
では、また。
この記事を書いた人
-
大学4年時春に文系就職を辞め、エンジニアになることを決意し、独学でRuby、Ruby on Railsを学習。
約1年間の独学期間を経てアーティスへWebエンジニアとして入社。現在はWebエンジニアとして、主にシステムの開発・運用に従事している。
抽象的なもの、複雑なものを言語化して文章にするのが好きで得意。
この執筆者の最新記事
- 2024年10月8日WEBVue3でjQueryのdatepickerを使いたい!実装手順と注意点を解説します。
- 2024年8月21日WEBVue3の非同期コンポーネントを使ってみる
- 2024年5月28日WEBLaravel×Inertia×Vue3でファイルアップロード機能を作ってみた
- 2024年4月15日WEBLaravel×Inertia×Vue3でCRUD機能を持つSPAを作ってみた
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー