Vue3系列 - 依赖注入的实现
Vue3中的依赖注入通过provide和inject函数实现,源码位于src/v3/apiInject.ts。
依赖注入的核心实现:
- provide函数:允许祖先组件向所有子孙组件提供数据。
export function provide<T>(key: InjectionKey<T> | string | number, value: T) {
if (!currentInstance) {
if (__DEV__) {
warn(`provide() can only be used inside setup().`)
}
} else {
resolveProvided(currentInstance)[key as string] = value
}
}- inject函数:允许子孙组件接收祖先组件提供的数据。
export function inject(
key: InjectionKey<any> | string,
defaultValue?: unknown,
treatDefaultAsFactory = false
) {
const instance = currentInstance
if (instance) {
const provides = instance.$parent && instance.$parent._provided
if (provides && (key as string | symbol) in provides) {
return provides[key as string]
} else if (arguments.length > 1) {
return treatDefaultAsFactory && isFunction(defaultValue)
? defaultValue.call(instance)
: defaultValue
} else if (__DEV__) {
warn(`injection "${String(key)}" not found.`)
}
}
}- 原型链查找:依赖注入利用JavaScript原型链机制,子组件可以访问到祖先组件提供的值。
export function resolveProvided(vm: Component): Record<string, any> {
const existing = vm._provided
const parentProvides = vm.$parent && vm.$parent._provided
if (parentProvides === existing) {
return (vm._provided = Object.create(parentProvides))
} else {
return existing
}
}- 类型安全:通过TypeScript的泛型和
InjectionKey接口提供类型安全。
依赖注入为深层组件通信提供了一种优雅的解决方案,避免了props逐层传递的问题。