# Vue.js 3 Composition API 実践ガイド完全ガイド【2025年最新版】
Vue.js 3 の Composition API は、Options API の代替として登場し、コンポーネントのロジックをより構造的に、再利用しやすく、テストしやすくするための強力なツールです。Options API では、データ、メソッド、ライフサイクルフックなどがコンポーネントのプロパティとして分割されていましたが、Composition API では関連するロジックを関数としてまとめ、`setup()` 関数内で定義できます。本記事では、Composition API の基本から応用までを解説し、実践的なコード例を豊富に交えながら、Vue.js 開発者の皆様が Composition API を習得し、より洗練されたコンポーネントを作成できるようサポートします。特に、リアクティビティ、リアクティブなデータ、`watch`、`computed`、そしてエラーハンドリングの実践的な例を重点的に解説します。
## 目次
1. はじめに
2. Composition API の基礎
2.1. `setup()` 関数
2.2. `ref` と `reactive`
2.3. `watch` 関数
2.4. `computed` プロパティ
3. 実践的なコード例
3.1. カウンターコンポーネント
3.2. データフェッチとエラーハンドリング
3.3. リアクティブなフォーム
3.4. カスタムフックの作成
3.5. 複数のコンポーネントへのデータ共有
4. `provide/inject` によるコンポーネント間通信
5. Vue Router と Composition API の連携
6. Vuex と Composition API の連携
7. パフォーマンス最適化
8. まとめ
## 1. はじめに
Vue.js 3 では、Composition API が標準的な書き方として推奨されています。Options API に慣れている方もいるかもしれませんが、Composition API はコードの可読性、再利用性、テスト容易性を向上させるための強力な機能を提供します。本ガイドでは、Composition API の基本概念から、より高度なテクニックまで、段階的に解説します。
## 2. Composition API の基礎
### 2.1. `setup()` 関数
`setup()` 関数は、Composition API のエントリポイントです。コンポーネントの初期化処理や、リアクティブなデータ、メソッドなどを定義する場所です。`setup()` 関数内で定義された変数は、テンプレート内で直接利用できます。
// App.vue
<template><p>{{ message }}</p></template><script>
import { ref } from 'vue';
export default {
setup() {
const message = ref('Hello, Vue 3 Composition API!');
return {
message
};
}
};
</script>
### 2.2. `ref` と `reactive`
`ref` は、プリミティブ型 (数値、文字列、真偽値など) の値をリアクティブにするために使用されます。一方、`reactive` は、オブジェクトや配列などの複合データ型をリアクティブにするために使用されます。
import { ref, reactive } from 'vue';
export default {
setup() {
const count = ref(0);
const user = reactive({
name: 'John Doe',
age: 30
});
return {
count,
user
};
}
};
`ref` は `.value` プロパティを使って値にアクセス・変更します。`reactive` は直接プロパティにアクセスします。
### 2.3. `watch` 関数
`watch` 関数は、リアクティブなデータが変化したときに実行されるコールバック関数を登録するために使用されます。これにより、データの変更に応じて副作用を実行できます。
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
watch(
count,
(newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
}
);
return {
count
};
}
};
### 2.4. `computed` プロパティ
`computed` プロパティは、リアクティブなデータの依存関係に基づいて自動的に再計算される値を定義するために使用されます。キャッシュされた値であり、依存関係が変更された場合にのみ再計算されます。
import { ref, computed } from 'vue';
export default {
setup() {
const width = ref(100);
const height = ref(100);
const area = computed(() => {
return width.value * height.value;
});
return {
width,
height,
area
};
}
};
: Composition API の基本概念を説明する図
## 3. 実践的なコード例
### 3.1. カウンターコンポーネント
<template><button @click="increment">Count: {{ count }}</button></template><script>
import { ref } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
};
</script>
### 3.2. データフェッチとエラーハンドリング
<template><div v-if="loading">Loading...</div><div v-else-if="error">Error: {{ error }}</div><div v-else>Data: {{ data }}</div></template><script>
import { ref, onMounted } from 'vue';
export default {
setup() {
const data = ref(null);
const loading = ref(true);
const error = ref(null);
onMounted(async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
data.value = await response.json();
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
});
return {
data,
loading,
error
};
}
};
</script>
### 3.3. リアクティブなフォーム
<template><input type="text" v-model="name"><p>Hello, {{ name }}!</p></template><script>
import { ref } from 'vue';
export default {
setup() {
const name = ref('');
return {
name
};
}
};
</script>
### 3.4. カスタムフックの作成
// useFetch.js
import { ref, onMounted } from 'vue';
export function useFetch(url) {
const data = ref(null);
const loading = ref(true);
const error = ref(null);
onMounted(async () => {
try {
const response = await fetch(url);
data.value = await response.json();
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
});
return { data, loading, error };
}
// App.vue
<template><div v-if="loading">Loading...</div><div v-else-if="error">Error: {{ error }}</div><div v-else>Data: {{ data }}</div></template><script>
import { useFetch } from './useFetch';
export default {
setup() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
return {
data,
loading,
error
};
}
};
</script>
### 3.5. 複数のコンポーネントへのデータ共有
// parent.vue
<template><p>Parent: {{ message }}</p><child :message="message"></child></template><script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: {
Child
},
setup() {
const message = ref('Hello from parent');
return {
message
};
}
};
</script>
// child.vue
<template><p>Child: {{ message }}</p></template><script>
import { defineComponent } from 'vue';
export default defineComponent({
props: {
message: {
type: String,
required: true
}
}
});
</script>
: カスタムフックの構造と使用方法を説明する図
## 4. `provide/inject` によるコンポーネント間通信
`provide/inject` は、祖先コンポーネントから子孫コンポーネントへデータを共有するためのメカニズムです。props を介した直接的な親子関係がない場合でも、データを共有できます。
## 5. Vue Router と Composition API の連携
Vue Router を Composition API と連携させることで、ルーティングの状態をリアクティブに扱うことができます。`useRoute` と ` useRouter` を使用することで、現在のルート情報やナビゲーション関数にアクセスできます。
## 6. Vuex と Composition API の連携
Vuex を Composition API と連携させることで、ストアの状態をリアクティブに扱うことができます。`useStore` を使用することで、ストアのインスタンスにアクセスできます。
: `provide/inject` の仕組みを図解した図
## 7. パフォーマンス最適化
Composition API を使用する際には、パフォーマンスを考慮したコーディングが重要です。リアクティブな変数の数を減らす、不要な再計算を避ける、`watch` 関数の効率化などが挙げられます。
## 8. まとめ
本ガイドでは、Vue.js 3 Composition API の基礎から応用までを解説しました。Composition API は、コンポーネントのロジックをより構造的に、再利用しやすく、テストしやすくするための強力なツールです。本記事で紹介した知識とコード例を参考に、Composition API を習得し、より洗練された Vue.js アプリケーションを開発してください。
**重要ポイントの再確認:**
* `setup()` 関数は Composition API のエントリポイント
* `ref` と `reactive` でリアクティブなデータを定義
* `watch` 関数でリアクティブなデータの変更を監視
* `computed` プロパティで依存関係に基づく再計算を定義
* カスタムフックでロジックを再利用可能にする
**実践へのアクションプラン:**
* 簡単なコンポーネントで Composition API を試す
* 既存の Options API コンポーネントを Composition API に移行する
* カスタムフックを作成してコードの再利用性を高める
**関連リソース:**
* [Vue.js 公式ドキュメント](https://vuejs.org/api/composition-api.html)
* [Vue Mastery – Composition API Course](https://www.vuemastery.io/courses/vue-composition-api)
※ 本記事の情報は執筆時点のものです。最新情報については各公式サイトをご確認ください。
コメント