provide-inject

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Provide/Inject

Provide/Inject

When managing data between parent and child components, Vue gives us the ability to use something known as props to pass data down from parent to child. Props can only flow in one direction, from parent components to child components (and further down). When state changes occur on parent elements, Vue will re-render components that depend on those values.
Using props works well in most cases. However, when working in large applications with a large number of components in the component tree, props can become hard to maintain since props need to be declared in each and every component in the component tree.
在管理父子组件间的数据时,Vue提供了props机制,用于从父组件向子组件传递数据。Props只能单向流动,从父组件到子组件(以及更深层级的组件)。当父组件的状态发生变化时,Vue会重新渲染所有依赖这些值的组件。
在大多数场景下,使用props是可行的。但在拥有大量组件的大型应用中,组件树层级较深时,props的维护会变得困难,因为需要在组件树的每一个中间组件中声明props。

When to Use

适用场景

  • Use this when you need to pass data through deeply nested component trees without prop drilling
  • This is helpful for application-wide data like themes, locale, or authentication state
  • 当你需要在深层嵌套的组件树中传递数据,且不想逐层传递props时使用
  • 适用于应用级别的数据,如主题、语言地区或认证状态等

When NOT to Use

不适用场景

  • For parent-child communication where props are simpler, more explicit, and easier to trace
  • When the implicit dependency makes components harder to test in isolation or reuse outside the provider tree
  • When a state management solution (Pinia) is already in place and provides the same shared state capability
  • 仅用于父子组件通信时,props更简单、明确且易于追踪
  • 当隐式依赖会导致组件难以独立测试或在提供者树外复用时
  • 当已经使用状态管理方案(如Pinia),且该方案已提供相同的共享状态能力时

Instructions

使用说明

  • Use
    provide()
    in a parent or ancestor component to make data available to all descendants
  • Use
    inject()
    in child components to access provided data
  • Use app-level
    app.provide()
    for data needed across the entire application (e.g., plugins)
  • Prefer props for data isolated to a specific set of components; use provide/inject for cross-cutting concerns
  • Be aware that debugging can be harder with provide/inject in large apps with many providers
  • 在父组件或祖先组件中使用
    provide()
    ,为所有后代组件提供可访问的数据
  • 在子组件中使用
    inject()
    来获取提供的数据
  • 对于整个应用都需要的数据(如插件),使用应用级别的
    app.provide()
  • 若数据仅针对特定组件集,优先使用props;跨组件的通用数据则使用provide/inject
  • 注意:在拥有多个提供者的大型应用中,使用provide/inject会增加调试难度

Details

详细说明

When considering how data can be managed between a large number of components, it's often best to work towards a solution that allows the management of application-level state in a maintainable and manageable manner (e.g. creating a reusable store, using Pinia, etc.). We talk about this in more detail in the State Management guide.
However, Vue also provides a certain pattern to help avoid the need for complex prop drilling in a Vue application known as the provide/inject pattern.
当考虑如何在大量组件间管理数据时,通常最好采用可维护、易管理的方案来处理应用级状态(例如创建可复用的store、使用Pinia等)。我们会在状态管理指南中详细讨论这一点。
不过,Vue也提供了一种模式,帮助避免Vue应用中复杂的props逐层传递问题,即provide/inject模式。

Provide/Inject

Provide/Inject

The
provide()
function in Vue allows us to pass data through a component tree without the need to prop-drill (i.e., pass props down manually at every level). On the other hand, the
inject()
option is used in child components to access the provided data or methods from their parent or any ancestor component.
We'll go through a simple example to illustrate how this can be done. Suppose we have a parent component called
App
that wants to share a piece of data with its child component,
ChildComponent
. Instead of passing this data as a prop, we can use
provide()
in the parent component to make the data available to all its child components.
html
<template>
  <div id="app">
    <ChildComponent />
  </div>
</template>

<script setup>
  import { provide } from "vue";
  import ChildComponent from "./components/ChildComponent";

  provide("data", "Data from parent!");
</script>
We can then access this provided data in the
ChildComponent
with the help of the
inject()
function.
html
<template>
  <div>
    <p>{{ data }}</p>
  </div>
</template>

<script setup>
  import { inject } from "vue";

  const data = inject("data");
</script>
By specifying
inject("data")
in the child component (
ChildComponent
), we directly access the provided
data
value from the parent component. We then bind
data
to the template to display its value.
With provide/inject, we would notice the same behavior even if we had numerous child components within the component hierarchy tree. Data from the parent
<App />
component will be rendered in any deeply nested child component without the need to prop-drill data through every component in the tree, thanks to provide/inject!
In addition to being able to
provide()
data from a parent component, we can lift the
provide()
up to the app level as well (i.e. where we instantiate our Vue application).
js
import { createApp } from "vue";
import App from "./App.vue";
import "./styles.css";

const app = createApp(App);

// app-level provide
app.provide("data", "Data from parent!");

app.mount("#app");
Since app-level provides make data available to all components, they are often helpful when creating plugins — self-contained code that adds functionality to the entire Vue app.
Vue中的
provide()
函数允许我们在组件树中传递数据,无需手动逐层传递props(即prop drilling)。而子组件可以使用
inject()
选项,从父组件或任意祖先组件中获取提供的数据或方法。
我们通过一个简单示例来演示如何使用。假设我们有一个名为
App
的父组件,想要与子组件
ChildComponent
共享一段数据。无需将数据作为props传递,我们可以在父组件中使用
provide()
,让所有子组件都能访问该数据。
html
<template>
  <div id="app">
    <ChildComponent />
  </div>
</template>

<script setup>
  import { provide } from "vue";
  import ChildComponent from "./components/ChildComponent";

  provide("data", "Data from parent!");
</script>
然后我们可以在
ChildComponent
中通过
inject()
函数访问这段提供的数据。
html
<template>
  <div>
    <p>{{ data }}</p>
  </div>
</template>

<script setup>
  import { inject } from "vue";

  const data = inject("data");
</script>
通过在子组件
ChildComponent
中指定
inject("data")
,我们可以直接从父组件中获取提供的
data
值,然后将其绑定到模板中显示。
使用provide/inject后,即使组件层级树中有多个子组件,也能实现同样的效果。父组件
<App />
中的数据会在任何深层嵌套的子组件中渲染,无需通过每一层组件逐层传递数据,这都要归功于provide/inject!
除了在父组件中使用
provide()
,我们还可以在应用级别(即初始化Vue应用的地方)使用
provide()
js
import { createApp } from "vue";
import App from "./App.vue";
import "./styles.css";

const app = createApp(App);

// 应用级别的provide
app.provide("data", "Data from parent!");

app.mount("#app");
由于应用级别的provide会让数据对所有组件可见,因此在创建插件时非常有用——插件是为整个Vue应用添加功能的独立代码。

Props vs. provide/inject

Props vs. provide/inject

When do we choose between props and the provide/inject pattern? Both approaches have their advantages and disadvantages.
我们应该在何时选择props,何时选择provide/inject模式?两种方式各有优缺点。

With props:

使用props:

  • We follow a clear pattern of passing data incrementally from one level to another (advantage).
  • However, if our component hierarchy tree contains a large number of components, the process of passing props data one level at a time can become cumbersome (disadvantage).
  • 遵循清晰的逐层传递数据的模式(优点)。
  • 但如果组件层级树包含大量组件,逐层传递props的过程会变得繁琐(缺点)。

With provide/inject

使用provide/inject

  • Child components can directly access data from parent components located multiple levels above, eliminating the need for passing down data at each level (advantage).
  • However, when bugs arise, debugging can be more challenging with provide/inject. This challenge becomes more pronounced in large-scale applications with numerous different providers (disadvantage).
The provide/inject pattern is most suitable for application-wide client data, such as theme information, locale/language preferences, and user authentication details. These types of data are better managed with provide/inject since any component within the application may require access to them at any given time.
On the other hand, props are ideal when data needs to be isolated within a specific set of components only.
  • 子组件可以直接访问多层级之上的父组件数据,无需逐层传递(优点)。
  • 但出现bug时,使用provide/inject的调试难度更高。在拥有大量不同提供者的大型应用中,这一挑战会更加明显(缺点)。
provide/inject模式最适合应用级别的客户端数据,如主题信息、语言地区偏好和用户认证详情等。这些类型的数据更适合用provide/inject管理,因为应用中的任何组件都可能随时需要访问它们。
另一方面,当数据仅需要在特定组件集中共享时,props是理想选择。

Source

来源

References

参考文档