はじめに (対象読者・この記事でわかること)

この記事は、Vue.jsの基本的な知識があるが、Vue 3への移行や新機能の使い方がわからない開発者を対象にしています。特に、Vue 2から移行を検討している方や、新規プロジェクトでVue 3を採用したい方に最適です。

この記事を読むことで、Vue 3の主要な新機能を理解し、Composition APIを使った効率的なコンポーネント開発ができるようになります。また、Vue 3での状態管理やパフォーマンス最適化の手法を学び、実際のプロジェクトに適用できるようになります。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 - JavaScriptの基本的な知識 - Vue 2の基本的な知識(オプショナルだがあるとスムーズ) - HTML/CSSの基本的な知識

Vue 3の概要と新機能

Vue 3は、2020年9月にリリースされた最新バージョンで、多くの新機能と改善が含まれています。最も注目すべきはComposition APIの導入で、これによりより柔軟なロジックの再利用が可能になりました。

その他の主要な新機能には、以下のようなものがあります:

  1. Composition API: ロジックを関数としてまとめ、再利用性を高めるための新しいAPI
  2. Teleport: コンポーネントのDOM構造を一時的に別の場所に移動できる機能
  3. Fragments: 複数のルート要素を持つコンポーネントがサポートされた
  4. Performance: Vue 2に比べてパフォーマンスが大幅に向上(特に起動速度とメモリ使用量)
  5. TypeScriptサポート: TypeScriptとの親和性が大幅に向上

これらの新機能により、より大規模で複雑なアプリケーション開発が容易になり、開発者の生産性が向上しています。

Vue 3での具体的な実装方法

ここでは、実際にVue 3を使ったWebアプリケーション開発の具体的な手順を解説します。特に「このような場合どのようにすれば実現できるか」という疑問に答えるため、実践的な例を交えて説明します。

ステップ1:プロジェクトのセットアップ

まずはVue 3のプロジェクトをセットアップします。Vue CLIやViteを使って新しいプロジェクトを作成できます。ここではViteを使った方法を紹介します。

Bash
# npmを使用する場合 npm create vite@latest my-vue3-app -- --template vue # yarnを使用する場合 yarn create vite my-vue3-app --template vue # プロジェクトディレクトリに移動 cd my-vue3-app # 依存関係をインストール npm install # 開発サーバーを起動 npm run dev

これで基本的なVue 3プロジェクトのセットアップが完了しました。

ステップ2:Composition APIを使ったコンポーネントの作成

Vue 3の最大の特徴であるComposition APIを使ったコンポーネントの作成方法を見ていきましょう。従来のOptions APIとの違いも確認します。

まず、従来のOptions APIでのコンポーネント例:

Vue
<template> <div> <p>カウント: {{ count }}</p> <button @click="increment">インクリメント</button> </div> </template> <script> export default { data() { return { count: 0 } }, methods: { increment() { this.count++ } } } </script>

これをComposition APIで書き直すと以下のようになります:

Vue
<template> <div> <p>カウント: {{ count }}</p> <button @click="increment">インクリメント</button> </div> </template> <script> import { ref } from 'vue' export default { setup() { const count = ref(0) function increment() { count.value++ } return { count, increment } } } </script>

Composition APIでは、setup()関数内でロジックを定義します。refを使って反応性を持つデータを定義し、関数としてロジックをまとめることができます。

さらに、<script setup>構文を使うと、より簡潔に書くことができます:

Vue
<template> <div> <p>カウント: {{ count }}</p> <button @click="increment">インクリメント</button> </div> </template> <script setup> import { ref } from 'vue' const count = ref(0) function increment() { count.value++ } </script>

<script setup>構文では、明示的にreturnする必要がなく、直接変数や関数を定義できます。これにより、コードがより簡潔になります。

ステップ3:状態管理の実装

Vue 3では、Vuexの代わりにPiniaが推奨される状態管理ライブラリです。Piniaはよりシンプルで型安全なAPIを提供しています。

まず、Piniaをインストールします:

Bash
npm install pinia

次に、main.jsでPiniaを設定します:

Javascript
import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const app = createApp(App) app.use(createPinia()) app.mount('#app')

次に、ストアを作成します。例えば、ユーザー情報を管理するストア:

Javascript
// stores/user.js import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ name: '', email: '', isAuthenticated: false }), actions: { login(userData) { this.name = userData.name this.email = userData.email this.isAuthenticated = true }, logout() { this.name = '' this.email = '' this.isAuthenticated = false } }, getters: { displayName: (state) => state.name || 'ゲスト' } })

コンポーネントでこのストアを使用するには:

Vue
<template> <div> <p>ようこそ、{{ displayName }}さん</p> <button v-if="!isAuthenticated" @click="login">ログイン</button> <button v-else @click="logout">ログアウト</button> </div> </template> <script setup> import { storeToRefs } from 'pinia' import { useUserStore } from '@/stores/user' const userStore = useUserStore() const { isAuthenticated, displayName } = storeToRefs(userStore) function login() { userStore.login({ name: '山田太郎', email: 'yamada@example.com' }) } function logout() { userStore.logout() } </script>

ステップ4:パフォーマンス最適化

Vue 3では、いくつかの手法でパフォーマンスを最適化できます。

  1. コンポーネントの遅延読み込み:
Javascript
const AsyncComponent = defineAsyncComponent(() => import('./components/AsyncComponent.vue') )
  1. v-memoによる不要な再レンダリングの抑制:
Vue
<template> <div v-memo="[value]"> <!-- valueが変更されない限り再レンダリングされない --> <p>{{ expensiveComputedValue }}</p> </div> </template>
  1. shallowRefとshallowReactive:
Javascript
import { shallowRef, shallowReactive } from 'vue' // オブジェクト全体の変更は検知するが、ネストされたプロパティの変更は検知しない const state = shallowRef({ count: 0 }) const reactiveState = shallowReactive({ nested: { count: 0 } })

ハマった点やエラー解決

Vue 3を使った開発でよく遭遇する問題とその解決策を紹介します。

問題1: Composition APIでrefの値が更新されない

Javascript
// 誤った例 function increment() { count++ // .valueを忘れている } // 正しい例 function increment() { count.value++ }

問題2: setup()で定義した変数がテンプレートで表示されない

Javascript
// 誤った例 setup() { const count = ref(0) // returnを忘れている } // 正しい例 setup() { const count = ref(0) return { count } }

問題3: TypeScriptで型エラーが発生する

Typescript
// 誤った例 const count = ref(0) // 型推論が正しくない場合がある // 正しい例 const count = ref<number>(0)

問題4: Piniaで状態が更新されない

Javascript
// 誤った例 state.count++ // 直接変更は推奨されない // 正しい例 store.increment() // action経由で変更する

解決策

これらの問題を解決するためのベストプラクティスは以下の通りです:

  1. Vue 3の公式ドキュメントを参照する: 最新の情報が得られます
  2. Vue DevToolsを使う: コンポーネントの状態やパフォーマンスを可視化できます
  3. TypeScriptを導入する: 型チェックにより多くのエラーを事前に検出できます
  4. Composition APIのベストプラクティスに従う: ロジックを再利用可能な関数として分割し、テストしやすくします

まとめ

本記事では、Vue 3の新機能とComposition APIを使ったモダンなWebアプリケーション開発手法について解説しました。

  • Composition APIの基本的な使い方
  • Piniaを使った状態管理
  • パフォーマンス最適化の手法
  • よくある問題とその解決策

この記事を通して、Vue 3を使った効率的で保守性の高いWebアプリケーション開発ができるようになったことと思います。特に、Composition APIを使ったロジックの再利用方法は、大規模なアプリケーション開発において非常に有効です。

今後は、Vue 3のさらなる高度な機能や、Nuxt 3との組み合わせについても記事にする予定です。

参考資料

参考にした記事、ドキュメント、書籍などがあれば、必ず記載しましょう。