Vue.js 3 - Composition API使用详解9(Provide/lnject依赖注入)
作者:hangge | 2026-05-07 08:42
我在之前的文章中演示了如何使用 Options API 中的 provide 和 inject 选项实现非父子组件之间的通信(点击查看)。 相比于 Options API 中的 provide 和 inject 选项,Composition API 中的 provide 和 inject 函数更加灵活和方便。下面我将通过样例进行演示。


(2)子组件(孙子组件)使用 inject 函数注入父组件(祖父组件)提供的响应式数据
九、Provide/lnject 依赖注入
1,提供数据
(1)provide 函数可以向子组件或孙子组件提供数据。它接收以下两个参数:
- key:要提供的键,可以是字符串或符号(symbol)。
- value:要提供的值。
(2)首先我们创建一个 Father.vue 父组件,首先在 setup 函数中调用 provide 函数为子组件或孙子组件提供 name 与 age 普通数据,以及 counter 响应式数据。其中,提供的普通数据是只读的,不可修改;提供的响应式数据默认是可读可修改的。
<template>
<div class="app" style="border:1px solid #ddd;margin:4px">
Father组件
<div>{{ name }} - {{ age }}</div>
<div>{{ counter }}</div>
<button @click="increment">Father组件+1</button>
<child />
</div>
</template>
<script>
import { provide, ref, readonly } from 'vue';
import Child from './Child.vue';
export default {
components: {
Child
},
setup() {
// 1.定义普通数据
const name = "hangge";
const age = 28;
// 2.定义响应式数据
let counter = ref(100);
// 3.给子组件提供数据
provide("name", name); // 提供普通数据(只能读,不能修改)
provide("age", age); // 提供普通数据(只能读,不能修改)
provide("counter", counter); // 提供响应式数据
const increment = () => counter.value++;
return { name, age, increment, counter }
}
}
</script>
2,注入数据
(1)在后代组件中,可以使用 inject 函数注入父组件 provide 函数提供的数据。inject 函数接收以下两个参数:
- key:需要注入的数据的名称。
- defaultValue(可选):在没有匹配到 key 时使用的默认值。
(2)这里我们创建一个 Child.vue 子组件,代码如下:
- 首先在 setup 函数中通过 inject 函数注入父组件或祖父组件 provide 函数提供的数据。其中,name 与 age 是普通对象(只能读,不能修改),counter 则是响应式对象(可读可修改)。
- 接着,在 homelncrement 函数中修改父组件提供的响应式数据 counter。
<template>
<div style="border:1px solid #ddd;margin:8px">
Child组件
<div>{{name}} - {{age}}</div>
<div>{{counter}}</div>
<button @click="homeIncrement">Child组件+1</button>
</div>
</template>
<script>
import { inject } from 'vue';
export default {
setup() {
const name = inject("name");
const age = inject("age");
const counter = inject("counter");
const homeIncrement = () => {
counter.value++
}
return {
name,
age,
counter,
homeIncrement
}
}
}
</script>
3,运行测试
(1)使用浏览器访问后显示效果如下:

(2)并且当单击“Father+1”按钮时,会在父组件中修改 counter。此时,Father.vue 组件和 Child.vue 组件的 counter 都会同步发生变化。同理,当单击“Child 组件+1”按钮时,会在子组件中修改 counter,此时 Father.vue 组件和 Child.vue 组件的 counter 也会同步发生变化。 因此,父组件提供了响应式数据,在子组件或孙子组件中仍然保持响应式。

附:进阶技巧
1,提供和注入响应式数据
(1)上面的样例我们知道 provide 函数不仅可以向子组件或孙子组件提供只读的普通数据,还支持提供响应式数据。比如下面父组件提供 ref 和 reactive 函数定义的响应式数据。
let counter = ref(100);
let info = reactive({
name: 'hangge',
age: 28
})
provide("counter", counter)
provide("info", readonly(info))
(2)子组件(孙子组件)使用 inject 函数注入父组件(祖父组件)提供的响应式数据
const counter = inject("counter");
const info = inject("info")
2,让响应式数据只读
(1)provide 函数提供的响应式数据既可以在父组件中被修改,又可以在子组件中被修改, 这会导致难以追踪数据的修改。
(2)为了保证单向数据流,以及避免子组件修改父组件提供的数据, 我们可以借助 readonly 函数,代码如下所示:
let counter = ref(100);
let info = reactive({
name: 'hangge',
age: 28
})
provide("counter", readonly(counter))
provide("info", readonly(info))
全部评论(0)