Vue3 面试原理部分
一.Vue3中依赖注入原理
在创建实例时会采用父组件的provides属性
const instance: ComponentInternalInstance = {
uid: uid++,
provides: parent ? parent.provides : Object.create(appContext.provides),
}
1
2
3
4
2
3
4
ProvideAPI
provides属性会向上查找父组件provides属性
export function provide<T>(key: InjectionKey<T> | string | number, value: T) {
if (!currentInstance) {
if (__DEV__) {
warn(`provide() can only be used inside setup().`)
}
} else {
let provides = currentInstance.provides // 获取当前实例的provides属性
const parentProvides =
currentInstance.parent && currentInstance.parent.provides
if (parentProvides === provides) { // 组件提供自己值的时候,用父组件的provides作为原型链创建新的对象
provides = currentInstance.provides = Object.create(parentProvides)
}
// TS doesn't allow symbol as index type
provides[key as string] = value
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
InjectAPI
查找provides中是否包含需要注入的属性
export function inject(
key: InjectionKey<any> | string,
defaultValue?: unknown,
treatDefaultAsFactory = false
) {
const instance = currentInstance || currentRenderingInstance
if (instance) {
const provides = // 获取provides值
instance.parent == null
? instance.vnode.appContext && instance.vnode.appContext.provides
: instance.parent.provides
if (provides && (key as string | symbol) in provides) { // 如果需要注入的属性在provides中
// TS doesn't allow symbol as index type
return provides[key as string] // 则将属性返回
} else if (arguments.length > 1) { // 注入式可以采用默认参数注入
return treatDefaultAsFactory && isFunction(defaultValue)
? defaultValue()
: defaultValue
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
依赖注入时,注入的数据来源不明确。不适合在业务代码中使用,可能会带来重构复杂的问题。(一般用于编写插件使用)