Vue.jsで親子コンポーネント間の値の受け渡しを行う際、props
やemit
が主に使われますが、ツリー構造が深くなるとコードが煩雑になりがちです。そんなときに役立つのがprovide/inject
の仕組みです。本記事では、基本的な使い方から、実践的な応用例、設計時の注意点まで詳しく解説します。
provide/injectとは?
provide/inject
は、Vue.jsの依存注入機能(Dependency Injection)です。祖先コンポーネントがprovide
で値を提供し、子孫コンポーネントがinject
で受け取ります。これにより、深い階層構造においても中間のpropsを省略でき、スッキリした設計が可能になります。
基本的な使い方
まずはシンプルな例で使い方を確認しましょう。
親コンポーネント(Provider)
<script setup>
import { provide } from 'vue';
const userName = '山田太郎';
provide('user', userName);
</script>
子コンポーネント(Injector)
<script setup>
import { inject } from 'vue';
const user = inject('user');
</script>
<template>
<p>こんにちは、{{ user }}さん</p>
</template>
このように、user
というキーで値を共有できます。
応用例:複数コンポーネント間で共通データを共有
たとえば、テーマカラーや言語設定などの共通設定を、アプリケーション全体で扱いたい場合にprovide/inject
が便利です。
App.vue で提供
<script setup>
import { provide, reactive } from 'vue';
const settings = reactive({
lang: 'ja',
theme: 'dark'
});
provide('settings', settings);
</script>
どこかの子孫コンポーネントで取得
<script setup>
import { inject } from 'vue';
const settings = inject('settings');
</script>
<template>
<div>
使用中の言語:{{ settings.lang }} / テーマ:{{ settings.theme }}
</div>
</template>
reactive
と組み合わせることで、変更もリアクティブに反映されます。
注意点と設計のポイント
provide/inject
は便利な反面、過剰に使うと依存関係が見えづらくなる恐れがあります。以下の点に注意しましょう。
- 共通状態はVuexやPiniaと比較検討する
- 意図的に限定的な用途に使う(テーマ・翻訳・認証など)
- injectした値が存在しない場合のデフォルト値やnullチェックを忘れない
まとめ
provide/inject
は、Vue.jsのコンポーネント設計を柔軟にし、特に大規模なアプリケーション開発においてpropsの煩雑さを軽減してくれる強力な仕組みです。使い方を誤らずに、責務を明確に保った設計を心がければ、メンテナンス性の高いコードを実現できます。