- 作者:老汪软件技巧
- 发表时间:2024-09-29 11:01
- 浏览量:
查找 provide 的数据:
数据的注入:
3. 详细源码分析
下面我们通过 Vue 的源码来进一步了解 provide 和 inject 的实现原理。
provide 的实现
在 Vue 中,provide 的逻辑实现很简单,主要是在组件实例化时,将 provide 的内容存储在组件实例的 _provided 属性中。
// Vue 源码片段:初始化 provide
export function initProvide(vm: Component) {
const provide = vm.$options.provide;
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm) // 如果是函数,则执行该函数
: provide; // 否则直接将对象存储
}
}
inject 的实现
在组件初始化时,Vue 会调用 resolveInject 函数来处理 inject 的注入过程。
// Vue 源码片段:解析 inject
export function resolveInject(inject: any, vm: Component): ?Object {
if (inject) {
const result = Object.create(null);
const keys = hasSymbol
? Reflect.ownKeys(inject)
: Object.keys(inject);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const provideKey = inject[key].from;
let source = vm;
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey];
break;
}
source = source.$parent; // 向上查找父组件,直到找到注入的 provide
}
}
return result;
}
}
resolveInject 的核心逻辑是:
遍历 inject 的 keys:获取需要注入的属性(可以是字符串数组或对象)。向上查找 provide:从当前组件的实例开始,逐级向上查找父组件的 _provided,直到找到包含 provide 数据的组件。注入数据:找到 provide 的数据后,将其注入到当前组件中。
如果没有找到对应的 provide 数据,Vue 并不会报错。也可以通过为 inject 提供默认值来避免数据未找到的情况。
4. 响应式处理
在 Vue 3 中,provide 和 inject 传递的默认数据不是响应式的。如果需要让提供的数据在后代组件中具备响应性,可以使用 Vue 3 的响应式 API,如 reactive 和 ref,让数据具备响应性。
响应式 provide 的示例
import { reactive, provide, inject } from 'vue';
// 父组件中提供响应式数据
export default {
setup() {
const state = reactive({
message: 'Hello from parent'
});
provide('state', state);
}
};
// 子组件中注入响应式数据
export default {
setup() {
const state = inject('state');
return {
state
};
}
};
是的,Vue 官方确实建议将 provide 和 inject 主要用于高阶插件或组件库开发,而不建议在普通应用程序中广泛使用它们。这是因为 provide 和 inject 设计初衷和适用场景的特殊性,使得它更适合在特定情况下使用。以下是官方建议及原因:
5.为什么 provide 和 inject 不推荐用于普通应用程序代码
隐式依赖关系:
调试困难:
不利于维护:
有限的双向数据绑定支持:
6.为什么 provide 和 inject 适合高阶插件/组件库?
跨层级状态共享:
灵活性和可扩展性:
解耦合设计:
封装复杂逻辑:
适用场景对比特性普通应用程序代码高阶插件/组件库
数据流动
倾向于使用 props 和事件
倾向于共享全局状态、上下文
依赖管理
依赖显式的父子组件传递
依赖注入,跨层级传递更灵活
调试和可维护性
调试更直观
插件开发时避免逐级传递
可读性
父子关系明确,数据流清晰
解耦合设计,依赖更灵活
应用场景
普通组件间的通信
跨层级的数据共享、插件开发
何时使用 provide 和 inject?
适合使用的场景:
总结