主题:依赖绑定以及触发依赖的执行策略
ps:多代码预警,本节因为涉及到的流程重要代码比较多,所以贴出了核心代码。
1.代理对象和影响因子effect如何绑定?(track)
上一篇文章讲的是响应型数据的诞生。而前面说过,响应数据的诞生和它绑定观察者是两回事。那么响应型对象和影响因子effect
是如何进行绑定依赖的呢?依赖的添加是在track
方法中,下面来进行讲解:
- 什么时候进行调用
track
方法?
可以看到基本上都在handlers
中进行调用,笔者对这些调用的方法进行追踪,发现调用者都在这里:
- baseHandlers.ts:
get
、has
、ownKeys
代理拦截方法里面进行追踪。 - collectionHandlers.ts:
get
、has
、size
、forEach
、iterator
方法里面进行追踪。 - ref.ts:在
value
方法中,也就是求值方法。
所以可以验证其那面的一句话:在获取数据的地方进行依赖的绑定。
-
在
track
方法中做了什么事情呢?下面我们会对整个流程所有必要代码进行解释,前面说过不会是以所有代码来进行讲解,只会讲解关键代码。/** * @description 追踪就是依赖的添加过程,相当于2.0的observer过程 * @param target 代理对象 * @param type 观察的类型,在开发环境中使用 * @param key 想要被观察的属性,也就是effect函数中访问的对象的属性 */ export function track(target: object, type: TrackOpTypes, key: unknown) { // 如果不是在观察依赖添加时期或者当前没有活跃的effect的时候,不进行任何处理 if (!shouldTrack || activeEffect === undefined) { return } // 接下来是进行构建targetMap的过程,详情可以查看附录2 let depsMap = targetMap.get(target) if (depsMap === void 0) { targetMap.set(target, (depsMap = new Map())) } let dep = depsMap.get(key) if (dep === void 0) { depsMap.set(key, (dep = new Set())) } // 进行响应数据和effect的互相绑定,dep是一个Set数据结构,这个是进行去重操作 if (!dep.has(activeEffect)) { dep.add(activeEffect) activeEffect.deps.push(dep) if (__DEV__ && activeEffect.options.onTrack) { activeEffect.options.onTrack({ effect: activeEffect, target, type, key }) } } }
看完上面代码,我们会想要知道
shouldTrack
和activeEffect
到底在什么时候进行:-
shouldTrack
:使用pauseTrack
和resumeTrack
进行修改shouldTrack
,而这两个方法在哪里进行调用呢?if (target.isUnmounted) { return } // disable tracking inside all lifecycle hooks // since they can potentially be called inside effects. pauseTracking() // 退出观测模式模式 // Set currentInstance during hook invocation. // This assumes the hook does not synchronously trigger other hooks, which // can only be false when the user does something really funky. setCurrentInstance(target) const res = callWithAsyncErrorHandling(hook, target, type, args) setCurrentInstance(null) resumeTracking() // 进入观测模式 return res })
我们可以从代码和注释中了解到,在除了
Unmounted
生命周期钩子之外,在其他声明周期钩子函数调用期间不进行追踪操作。 -
activeEffect
:在执行effect
函数之前,会进行effect
赋值给activeEffect
(effect
是一个带有属性的方法实例),在执行期间会进行依赖的绑定。function run(effect: ReactiveE
-