Vue 的 provide
和 inject
provide
和 inject
是 Vue 中用于跨层级组件通信的一对 API。这对 API 通常用于在组件树中共享数据或方法,而不需要通过层层传递 props
和 emit
。它们适合用在组件层级较深的场景,例如全局状态管理、依赖注入或插件开发。
工作原理
provide
:在祖先组件中定义需要共享的数据或方法。inject
:在后代组件中接收provide
提供的数据。
这些数据通过 Vue 的依赖注入机制自动关联,而无需显式传递。
基本用法
1. 定义 provide
在祖先组件中,通过 provide
提供数据:
<script setup lang="ts">
import { ref, provide } from 'vue';
// 定义一个共享的状态
const sharedState = ref('Hello, Vue!');
// 使用 provide 提供数据
provide('sharedState', sharedState);
</script>
<template>
<div>
<p>祖先组件内容</p>
<slot></slot>
</div>
</template>
2. 使用 inject
在后代组件中,通过 inject
接收数据:
<script setup lang="ts">
import { inject } from 'vue';
// 使用 inject 获取祖先组件提供的数据
const sharedState = inject('sharedState');
</script>
<template>
<div>
<p>后代组件内容:{{ sharedState }}</p>
</div>
</template>
响应式数据的支持
通过 provide
和 inject
传递的响应式数据依然保持响应性,因为 Vue 会处理数据的 reactivity 绑定。例如,若 sharedState
是一个 ref
,在后代组件中修改它会影响到祖先组件。
高级用法
1. 动态注入多种数据
provide
可以提供多个键值对:
<script setup lang="ts">
import { provide } from 'vue';
provide('theme', 'dark');
provide('user', { name: 'Alice', role: 'admin' });
</script>
后代组件可以选择性地注入:
<script setup lang="ts">
import { inject } from 'vue';
const theme = inject('theme', 'defaultTheme'); // 设置默认值
const user = inject('user');
</script>
<template>
<div>
<p>主题:{{ theme }}</p>
<p>用户:{{ user.name }}(角色:{{ user.role }})</p>
</div>
</template>
2. 使用工厂函数
provide
支持通过工厂函数动态生成值:
<script setup lang="ts">
import { provide } from 'vue';
const createLogger = () => {
return {
log: (message: string) => console.log(`[Logger] ${message}`)
};
};
provide('logger', createLogger());
</script>
后代组件使用:
<script setup lang="ts">
import { inject } from 'vue';
const logger = inject('logger');
logger.log('注入的日志功能生效');
</script>
3. 依赖注入
在插件或服务模式中,provide
和 inject
是实现依赖注入的关键。例如,一个全局服务可以通过 provide
注入,供多个后代组件使用。
限制与注意事项
-
provide
和inject
不是响应式 API 本身:- 如果传递的值不是响应式数据(如普通对象),后代组件中不会响应数据变化。
- 确保传递的值是响应式的,例如使用
ref
或reactive
。
-
作用范围受限:
provide
的数据仅对组件树中的后代组件可见。- 兄弟组件之间无法通过
inject
共享数据。
-
默认值:
- 若
inject
无法找到对应的provide
值,可以设置一个默认值避免报错。
- 若
-
组合式 API 与选项式 API 的差异:
- 在选项式 API 中,
provide
和inject
是对象:export default { provide: { theme: 'dark', user: { name: 'Bob' }, }, inject: ['theme', 'user'], };
- 在组合式 API 中,它们是函数,提供更灵活的写法。
- 在选项式 API 中,
实际应用场景
-
主题管理:
- 用
provide
提供当前主题,后代组件可以通过inject
动态调整样式。
- 用
-
表单管理:
- 祖先组件提供全局表单状态,后代组件(如输入框、按钮)共享状态。
-
插件开发:
- 插件通过
provide
提供全局服务(如路由、状态管理)。
- 插件通过
-
跨组件通信:
- 当组件层级很深时,用于避免繁琐的
props
和事件传递。
- 当组件层级很深时,用于避免繁琐的
总结
provide
和 inject
是 Vue 提供的简单高效的跨组件共享机制。它们适合轻量级的状态共享和依赖注入,但在复杂的全局状态管理中,推荐使用更强大的工具(如 Pinia 或 Vuex)。