依存性注入のためのprovide()とinject()
祖先コンポーネントで値を提供し、ツリーの深い階層で注入することで、状態管理ライブラリ全体を導入せずにpropsのバケツリレーを避けます。
「依存性注入のためのprovide()とinject()」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。
Prop Drillingの問題
データが上位のコンポーネントにあり、深い階層の子孫コンポーネントまで渡す必要がある場合があります。すべての中間コンポーネントを経由して渡すこと(prop drilling)は、手間がかかり壊れやすい方法です。
provide() — 値の宣言
祖先コンポーネントでprovide(key, value)をsetup()内から呼び出します。その値はすべての子孫コンポーネントから利用できるようになります。
<!-- ParentComponent.vue -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
</script>inject() — 値の利用
任意の子孫コンポーネントでinject(key)を呼び出すと、その値を読み取れます。
<!-- DeepChild.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
<template>
<div :class="theme">Theme is: {{ theme }}</div>
</template>ref/reactiveによるリアクティビティ
refまたはreactiveオブジェクトをprovideすると、子孫コンポーネントはリアクティブな値を取得し、更新が自動的に伝播します。
// Parent
const user = reactive({ name: 'Alice', role: 'admin' });
provide('user', user);
// Anywhere descendant
const user = inject('user');
user.role; // 'admin' — reactive衝突を避けるためのSymbolキー
大規模なアプリでは、文字列キーが衝突するおそれがあります。Symbolを使えば一意性を保証できるため、共有ファイルで定義してください。
// keys.ts
export const ThemeKey = Symbol('theme');
export const UserKey = Symbol('user');
// Parent
provide(ThemeKey, ref('dark'));
// Child
const theme = inject(ThemeKey);TypeScriptのサポート
InjectionKey<T>を使用すると、provideする側とinjectする側の両方を型安全にできます。
import type { InjectionKey, Ref } from 'vue';
export const ThemeKey: InjectionKey<Ref<string>> = Symbol('theme');
// Provider:
provide(ThemeKey, ref('dark'));
// Consumer (type-checked):
const theme = inject(ThemeKey); // Ref<string> | undefinedデフォルト値
どの祖先コンポーネントもキーをprovideしていない場合、デフォルト値を渡さない限りinjectはundefinedを返します。
const theme = inject('theme', 'light'); // default if missing
const lazy = inject('user', () => createDefaultUser(), true); // factory読み取り専用のProvide
子孫コンポーネントによる共有状態の変更を防ぐには、readonly()でラップしてください。
import { readonly } from 'vue';
const user = reactive({ name: 'Alice' });
provide('user', readonly(user));
// Children can read but cannot mutateアプリレベルのProvide
アプリケーションレベルで値をprovideすると、どこからでも利用できるようになります。プラグインに便利な方法です。
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.provide('apiClient', new ApiClient());
app.mount('#app');Composableによるラッパー
provide/injectをComposableでラップすると、利用側のAPIをより扱いやすくできます。
// useTheme.ts
import { inject, type InjectionKey, type Ref } from 'vue';
export const ThemeKey: InjectionKey<Ref<string>> = Symbol('theme');
export function useTheme() {
const theme = inject(ThemeKey);
if (!theme) throw new Error('useTheme: no provider in tree');
return theme;
}provide/injectとPiniaの比較
provide/inject:軽量でライブラリが不要です。テーマ、ロケール、現在のユーザーなど、プラグイン形式の値に適しています。Pinia:DevToolsを備えた完全な状態管理で、複雑な更新を伴うアプリ全体のリアクティブな状態に適しています。
確認問題
大規模なVueアプリでprovide/injectを使用する際、キーの衝突を避けるために推奨される方法は何ですか?
まとめ:provide/inject
祖先コンポーネントがprovideし、子孫コンポーネントがinjectするため、prop drillingは不要です。リアクティブな値(ref/reactive)はリアクティブに伝播します。SymbolキーとInjectionKeyにより、型安全で衝突のないinjectを実現できます。injectの第2引数でデフォルト値を指定できます。変更を防ぐにはreadonly()を使用します。アプリ全体で使うプラグインにはアプリレベルのprovideを使用します。プラグイン形式の値には、Piniaに代わる軽量な方法です。
よくある質問
「依存性注入のためのprovide()とinject()」レッスンは無料ですか?
はい。「依存性注入のためのprovide()とinject()」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Frontend Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Frontend Academyコースには全4レッスンが含まれています。
「依存性注入のためのprovide()とinject()」で何を学びますか?
祖先コンポーネントで値を提供し、ツリーの深い階層で注入することで、状態管理ライブラリ全体を導入せずにpropsのバケツリレーを避けます。 ブラウザで直接実行するハンズオンコードでFrontend Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Frontend Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのFrontend Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「依存性注入のためのprovide()とinject()」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このFrontend Academyレッスンでコードを書いて実行できますか?
はい。すべてのFrontend Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 依存性注入のためのprovide()とinject()
- 非同期コンポーネントとSuspense
- カスタムディレクティブ
- プラグインシステム:app.use()