Computed计算属性与Watch观察器
前言
本章我们开始介绍 Vue.js 的Computed计算属性与Watch观察器模块的源码,我们将在本章详细介绍这两个模块背后的原理。
希望经过本篇文章的介绍能够让读者对于Computed与Watch的实现原理与实际使用更加深入。
Computed计算属性
computed函数
Vue.js 3.0 使用computed函数来创建一个新的计算属性,computed接收Get、Set以及debugOptions参数,
默认情况下Set将会为空,Get函数里面的响应式数据将会作为依赖被收集。
// computed
export function computed<T>(
getter: ComputedGetter<T>,
debugOptions?: DebuggerOptions
): ComputedRef<T>ComputedRefImpl
ComputedRefImpl是Computed计算属性的实际控制器,每当创建一个新的计算属性Computed便会构造一个新的ComputedRefImpl类,
首先ComputedRefImpl为每一个计算属性构造了一个新的effect,这个effect用于收集计算属性的依赖dep,
每当计算属性被引用时,执行trackRefValue函数将get中所遇到响应式数据的dep与之前所创建好的effect收集器完成绑定,从而完成计算属性对于其内部响应式数据的收集。
每当被收集的响应式数据更新时,effect会去执行effect.run操作将计算属性的更新推入下一个微任务更新队列中,更新视图。
最后dirty属性将标识缓存本次计算所得到的结果,除非依赖被更新时effect上面的scheduler回调函数才会被执行dirty变回到true,
开始重新执行计算属性的结果值。
Watch观察器
Watch观察器的组成部分
在 Vue.js 3.0 中watch观察器存在watchEffect与watch函数两种,而其本质均是doWatch的变体函数。
一个完整的watch观察器主要包括两个部分:
Getter:被观察的属性,在watchEffect中是回调函数
SchedulerJob:被执行的回调函数
getter
getter存在三种不同情形,当被观察的是一个响应式数据ref或者reactive时,其返回的是被观察的响应式数据本身,
而当需要同时观察多个数据时,其返回的则是被观察的响应式数据的一维数据,与计算属性相同,这里的数据同样会被依赖收集。
最后当被观察的是一个函数时,其返回的则是一个被callWithErrorHandling包裹的高阶函数。
watchJob
在watch观察器中getter属于被观察的对象,而watchJob则是执行函数,与计算属性相同watch观察器中同样会构建effect用于依赖收集与组件更新。
watchJob的执行分为三种情况,当immediate属性存在时watchJob会被当做独立函数立即执行,当依赖被更新或者组件更新时,effect将会被运行。
而当flush === 'post'时,这个运行会被延后到组件刷新后的下一个微任务队列中。
当watchJob被执行时同样会分为两种情况,当被观察的是响应式数据时,其与computed计算属性相同会收集响应式的dep依赖,当依赖更新时才会被触发,
而当被观察的是函数时,这个effect会被关联到当前的effectscope作用域中,每当组件或者effectscope需要更新时,开始执行。
stopWatcher
watch函数会返回一个stop函数,当执行stop时,watch会销毁这个effect并从当前的effectScope中移除。
总结
本章我们详细的介绍了Computed计算属性与Watch观察器的运行机制。
本章内容并不复杂,读懂本章的核心仍然是在理解effect与schduler这两个模块,Computed与Watch均是在此基础上而来的。
对于effect与schduler模块请阅读本系列文章的对应章节。
Last updated