Contents
Vue 3 と Composition API の概要とメリット
Vue 3 が提供する Composition API は、コンポーネントのロジックを関数単位で切り出す新しい記法です。従来の Options API に比べてコードの再利用性や可読性が向上し、大規模開発でも保守コストを抑えることができます。本セクションでは、Composition API の基本概念と、実際に導入することで得られる主なメリットを解説します。
Composition API とは
Composition API は setup() 関数内で Vue のリアクティブ機能(ref, reactive など)やライフサイクルフックを利用できる仕組みです。以下のポイントが特徴です。
- 関数ベース:ロジックを独立した関数にまとめられるため、単体テストが容易になる
- 型推論が自然:TypeScript と併用すれば、IDE が自動補完や型チェックを行ってくれる
- スコープの明確化:同一コンポーネント内で複数機能を分割でき、名前衝突を防止できる
従来の Options API との違い
Options API は data, methods, computed といったオプションをオブジェクトに列挙しますが、構造上いくつか制約があります。下表は両者の主な相違点をまとめたものです。
| 項目 | Options API | Composition API |
|---|---|---|
| ロジックの分割単位 | コンポーネント全体に限定 | 任意の関数へ自由に切り出し可能 |
| 型推論・型安全性 | Vue 2 系列では限定的 | 完全な TypeScript サポート |
| 再利用性 | Mixin / Extends に依存 | カスタムフック(Composition 関数)で簡潔に共有 |
要点:Composition API は可読性・再利用性・型安全性の三点で Options API を上回り、モダンなフロントエンド開発に最適です。
開発環境の構築:Node.js·npm と Vite(TypeScript オプション)
Vue 3 のプロジェクトは軽量かつ高速なビルドツール Vite が公式に推奨されています。本セクションでは、2026 年時点で提供されている最新の LTS 版 Node.js と npm を使用した環境構築手順、および TypeScript の導入方法を具体的に示します。
Node.js と npm のインストール手順
まずは公式サイト(https://nodejs.org/)から「LTS」ラベルが付いた最新版をダウンロードし、インストーラの指示に従ってインストールしてください。インストール後、ターミナルで以下コマンドを実行するとバージョンが表示されます。
|
1 2 3 |
node -v # 例: v20.x.x(最新 LTS が出力されます) npm -v # 例: 10.x.x 以上 |
ポイント:
node -vの結果は環境ごとに異なるため、固定のバージョン番号を書かず「最新 LTS を利用する」ことを推奨します。
Vite プロジェクト作成コマンド
次にプロジェクト用ディレクトリを作り、Vite の Vue テンプレートからスタートします。以下の手順は npm 経由で実行します。
|
1 2 3 4 5 6 |
# 作業ディレクトリの作成と移動 mkdir vue-composition-tutorial && cd $_ # Vite + Vue 3 テンプレートでプロジェクト生成 npm create vite@latest . -- --template vue |
テンプレートが生成されたら、依存パッケージをインストールします。
|
1 2 |
npm install |
TypeScript 設定の追加
TypeScript を利用したい場合は、Vite が提供する公式プラグインと型チェックツールを導入します。手順は次の通りです。
-
必要な開発依存パッケージをインストール
bash
npm i -D typescript @vitejs/plugin-vue vue-tsc -
tsconfig.jsonの雛形を生成(Vite が自動的に作成)
bash
npx vite-plugin-vue-type-check --init -
package.jsonに型チェック用スクリプトを追加
json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"type-check": "vue-tsc --noEmit"
}
}
まとめ:Node.js と npm をインストールし、Vite の Vue テンプレートを用いれば数分で最新の Vue 3 + TypeScript 開発環境が完成します。バージョン番号は「最新版 LTS」を参照する形にしておくと、将来的な更新作業が不要です。
Composition API の基本実装:setup() とリアクティブ API
setup() 関数はコンポーネント生成時に最初に呼び出され、ここでリアクティブ状態やロジックを定義します。本節では ref, reactive, computed, watch の使い分けと、シンプルなカウンター例を通じて実装手順を解説します。
setup() 関数の構造
Vue コンポーネントは次のようにエクスポートし、setup() が返すオブジェクトのプロパティがテンプレートで利用可能になります。以下は最小構成のサンプルです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<script setup lang="ts"> import { ref, reactive, computed } from 'vue' const count = ref(0) // 単一値は ref で管理 const state = reactive({ // 複数フィールドは reactive が便利 name: '', age: 0 }) const doubleCount = computed(() => count.value * 2) function increment() { count.value++ } </script> <template> <div> <p>カウント: {{ count }} ({{ doubleCount }})</p> <button @click="increment">+1</button> </div> </template> |
reactive と ref の使い分け
ref と reactive は目的に応じて選択します。
- ref:プリミティブ型(数値・文字列)や単一オブジェクトをリアクティブ化したいとき。
.valueでアクセスする必要があります。 - reactive:オブジェクト全体をリアクティブにし、プロパティへ直接アクセスできる点が特徴です。
computed と watch の実例
以下は金額計算と在庫監視の典型的なユースケースです。computed は派生状態の自動再計算に、watch は副作用処理に適しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { ref, computed, watch } from 'vue' const price = ref(1200) // 単価 const quantity = ref(1) // 購入数 // 合計金額は自動的に再計算される const total = computed(() => price.value * quantity.value) // 在庫が 10 個を超えると警告ダイアログを表示 watch(quantity, (newVal) => { if (newVal > 10) alert('在庫が不足しています') }) |
ポイント:setup() 内でリアクティブ API を組み合わせるだけで、状態管理・副作用処理がシンプルに記述できます。
コンポーネント間通信と再利用可能なロジック
Composition API はコンポーネント同士のデータ受け渡しや共通ロジックの抽象化を容易にします。本節では props/emit、provide/inject、そしてカスタム Composition 関数 の作り方と実装例をご紹介します。
props と emit の基本
子コンポーネント側で受け取るプロパティと外部へ通知するイベントを宣言するには defineProps と defineEmits を使用します。以下は文字列メッセージを受信し、ランダムな数値を親に返す例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!-- ChildComponent.vue --> <script setup lang="ts"> const props = defineProps<{ msg: string }>() const emit = defineEmits<{ (e: 'update', newVal: number): void }>() function sendUpdate() { emit('update', Math.random()) } </script> <template> <div> <p>受信メッセージ: {{ props.msg }}</p> <button @click="sendUpdate">更新通知</button> </div> </template> |
親コンポーネントは次のように子を組み込み、イベントハンドラで値を取得します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<script setup lang="ts"> import ChildComponent from './ChildComponent.vue' import { ref } from 'vue' const parentMsg = ref('こんにちは') function handleUpdate(val: number) { console.log('子から受信:', val) } </script> <template> <ChildComponent :msg="parentMsg" @update="handleUpdate"/> </template> |
provide / inject の活用例
階層が深いコンポーネント間で状態を共有したい場合は provide と inject が便利です。以下のサンプルではテーマ情報(文字列)を上位コンポーネントから下位へ流しています。
|
1 2 3 4 5 6 7 8 9 |
<!-- Provider.vue --> <script setup lang="ts"> import { provide, ref } from 'vue' const theme = ref('dark') provide('theme', theme) // キーは文字列か Symbol が推奨 </script> <template><slot/></template> |
|
1 2 3 4 5 6 7 8 |
<!-- Consumer.vue --> <script setup lang="ts"> import { inject, type Ref } from 'vue' const theme = inject<Ref<string>>('theme')! </script> <template>現在のテーマ: {{ theme }}</template> |
カスタム Composition 関数(フック)の作り方
共通ロジックは独立した関数として切り出すことで、複数コンポーネントで再利用できます。ここでは タイマー 用フック useTimer を実装し、0.5 秒ごとにカウントアップする例を示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// src/composables/useTimer.ts import { ref, onMounted, onUnmounted } from 'vue' export function useTimer(intervalMs: number = 1000) { const count = ref(0) let timerId: ReturnType<typeof setInterval> onMounted(() => { timerId = setInterval(() => { count.value++ }, intervalMs) }) onUnmounted(() => clearInterval(timerId)) return { count } } |
コンポーネント側での使用例です。
|
1 2 3 4 5 6 7 8 9 |
<script setup lang="ts"> import { useTimer } from '@/composables/useTimer' const { count } = useTimer(500) // 0.5 秒ごとにインクリメント </script> <template> <p>経過秒数: {{ count }}</p> </template> |
まとめ:props/emit、provide/inject、そしてカスタム Composition 関数を組み合わせることで、コンポーネント間通信とロジックの再利用がシンプルかつ型安全に実現できます。
移行ガイドライン・デバッグ・ビルド・デプロイ
既存の Options API プロジェクトを Composition API に置き換える際の手順や、開発中に役立つ Vue Devtools の活用法、最終的な本番デプロイまでのフローをまとめました。
Options API からの段階的移行ポイント
- ロジック単位で抽出
data,methods,computedを機能ごとに分割し、useXxx()と命名した関数へ移す。- setup() に統合
- 抽出した関数を
setup()内で呼び出し、必要なプロパティだけを返す形にする。 - 型安全の確保
- TypeScript が有効なら
ref<T>・reactive<T>に明示的なジェネリクス型注釈を付与すると、移行後のエラーが大幅に減ります。
注意点
-thisは使用できません。すべてsetup()のローカル変数で代替してください。
- ライフサイクルはonMounted,onBeforeUnmountなど Composition 系へ置き換える必要があります。
Vue Devtools の活用法
- コンポーネントツリー:リアクティブ状態(
ref,reactive)が即座に表示され、期待通りに更新されているかを視覚的に確認できます。 - タイムトラベルデバッグ:Pinia と併用するとステート遷移履歴を遡って検証でき、バグの原因追求が容易です。
- パフォーマンスプロファイラ:
Performanceタブで再レンダリング回数やコストを測定し、不要なリアクティビティの発生源を特定します。
ビルド・デプロイの標準フロー
| 手順 | コマンド例 | 主な目的 |
|---|---|---|
| 開発サーバ起動 | npm run dev |
Vite の開発モードでホットリロードを有効化 |
| 型チェック(TypeScript) | npm run type-check |
ビルド前に型エラーを検出 |
| 本番ビルド作成 | npm run build |
最適化済みの静的ファイルが dist/ に生成 |
| プレビュー確認 | npm run preview |
ローカルで本番ビルドの動作を検証 |
| 静的ホスティングへデプロイ | npm run build && npx netlify deploy --dir=dist(例) |
Netlify、Vercel、Firebase Hosting など好みのサービスにアップロード |
ベストプラクティス
- ビルド前に必ずtype-checkとユニットテストを実行し、品質を保証する。
- 環境変数は.env.productionに分離し、Vite のimport.meta.envで参照すると安全です。
要点:段階的な移行と Vue Devtools を活用したデバッグによりリスクを最小化しつつ、Composition API へのシフトが実現できます。ビルド・デプロイは Vite が提供するコマンドだけで完結できるため、開発フローが大幅に簡素化されます。