在 Vue 3 中,provide
和 inject
是一对组合式 API,用于在组件树中进行跨层级的数据共享,而无需通过 props
或 emit
逐层传递。
使用场景
- 当祖先组件需要向后代组件共享数据,而中间层组件不需要参与时。
- 当数据需要在多个不直接相关的组件之间共享时。
provide
和 inject
的基本用法
1. 在祖先组件中使用 provide
provide
用于定义要共享的数据。
import { provide } from 'vue';
export default {
setup() {
const sharedData = 'Hello from parent';
provide('sharedKey', sharedData); // 提供数据
return {};
}
};
provide
接收一个键值对,'sharedKey'
是键,sharedData
是值。- 这个数据会被共享到组件树中的后代组件。
2. 在后代组件中使用 inject
inject
用于接收祖先组件提供的数据。
import { inject } from 'vue';
export default {
setup() {
const sharedData = inject('sharedKey'); // 接收数据
console.log(sharedData); // 输出 "Hello from parent"
return { sharedData };
}
};
- 如果提供的键不存在,
inject
会返回undefined
,你可以提供默认值:const sharedData = inject('sharedKey', 'Default Value');
响应式支持
非响应式数据:
默认情况下,通过provide
和inject
共享的数据是非响应式的。如果需要响应式,应该显式使用 Vue 的响应式 API。import { provide, reactive } from 'vue'; export default { setup() { const sharedData = reactive({ message: 'Hello from parent' }); provide('sharedKey', sharedData); // 提供响应式数据 return {}; } };
后代组件:
import { inject } from 'vue'; export default { setup() { const sharedData = inject('sharedKey'); console.log(sharedData.message); // 响应式:改变父组件的 message 会同步 return { sharedData }; } };
仅需要响应式引用:
如果只想共享响应式引用而非整个对象,可以使用ref
:import { provide, ref } from 'vue'; export default { setup() { const count = ref(0); provide('countKey', count); return {}; } };
注意事项
作用域:
- 数据只能在
provide
和inject
所在的组件树内使用。 - 如果后代组件超出了提供组件的作用域,则无法访问该数据。
- 数据只能在
非响应式问题:
- 共享的是普通变量时,更新变量不会自动触发视图更新。
- 如果需要响应式,确保使用
reactive
或ref
。
多层嵌套组件:
inject
会自动查找最近的provide
。
高级用法
多个数据提供:
你可以在provide
中提供多个值:provide('key1', value1); provide('key2', value2);
函数作为值:
你可以通过函数来动态计算数据:provide('getMessage', () => 'Dynamic Message');
后代组件:
const getMessage = inject('getMessage'); console.log(getMessage()); // 调用函数获取值
总结
provide
和inject
提供了一种简单的方式在 Vue 组件树中实现跨层级数据共享。- 它们避免了
props
和事件的逐层传递,适合管理全局状态或共享逻辑。 - 对于复杂的场景,Vue 提供的 Pinia 或 Vuex 可能是更好的选择。