provide/inject 让祖先组件向任何后代供应数据,无论有多深,而无需通过每个中间组件传递 props。它们解决了prop drilling。
问题: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
提供响应式对象(ref,而不是其 .value),以便在更改时,所有注入的组件都会更新。
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)区分开来,让你能够干净地通过深层组件树传递共享上下文。