provide/inject により、祖先コンポーネントが任意の子孫にデータを供給でき、深さに関係なく、すべての中間コンポーネントを通じてpropsを渡す必要がありません。これはprop drillingを解決します。
なぜ重要なのか
text
App → Layout → Sidebar → Menu → MenuItem
だけがを必要とする場合、それを、、および(これらはそれを使用しない)を通じてpropとして渡すことは退屈で煩雑です。/はその中間を飛ばします。
MenuItemthemeLayoutSidebarMenuprovideinject<!-- App.vue -->
<script setup>
import { provide, ref } from "vue";
const theme = ref("dark");
provide("theme", theme); // make `theme` available to ALL descendants
provide("toggleTheme", () => { // can provide functions too
theme.value = theme.value === "dark" ? "light" : "dark";
});
</script>
<!-- MenuItem.vue (deeply nested) -->
<script setup>
import { inject } from "vue";
const theme = inject("theme"); // get it directly — no props in between
const toggleTheme = inject("toggleTheme");
const color = inject("color", "blue"); // with a default fallback
</script>
// ✅ provide a ref/reactive so descendants see updates
provide("theme", theme); // theme is a ref → reactive
// ❌ provide("theme", theme.value) → passes a snapshot, not reactive
リアクティブなオブジェクト(.valueではなくref)を提供し、それが変わるとすべての注入コンポーネントが更新されるようにします。
import { themeKey } from "./keys"; // export const themeKey = Symbol()
provide(themeKey, theme); // avoids string-key collisions
provide/inject → pass data down a specific subtree (theme, form context, a service)
Pinia → global, app-wide shared state (user, cart) usable anywhere
provide/injectはサブツリー内の依存性注入に使用します。アプリの真に真のグローバルまたは関連のない部分全体で共有されるような状態にはPiniaを使用してください。
provide/injectは、多くのネストされたコンポーネントが共有するデータ(テーマ、ロケール、フォーム/コンテキスト、プラグインサービス)のprop drillingを排除します。
リアクティブ値を提供する方法(更新が伝播するように)、デフォルト/Symbolキーを使用する方法、グローバル状態(Pinia)との区別を知ることにより、深いコンポーネントツリーを通じて共有コンテキストをクリーンに渡すことができます。