源码分析
initComputed
initComputed这段代码做了几件事
- 每个computed配发watcher;
- defineComputed处理;
- 收集所有computed的watcher;
watcher做了什么
看下Watcher源码构造函数
- computed新建watcher的时候,传入lazy,作用是把计算结果缓存起来,而不是每次使用都要重新计算;
- 保存设置的 getter,把用户设置的 computed-getter,存放到 watcher.getter 中,用于后面的计算;
- watcher.value 存放计算结果,但是这里有个条件,因为 lazy 的原因,不会新建实例并马上读取值;这里可以算是 Vue 的一个优化,只有你再读取 computed,再开始计算,而不是初始化就开始计算值了,虽然没有一开始计算,但是计算 value 还是这个 watcher.get 这个方法;
defineComputed 处理
- set函数默认是空函数,如果用户设置了,则使用用户设置;
- 如果使用缓存,则get方法通过createComputedGetter包装,否则用createGetterInvoker进行包装;
- 将set方法和get方法封装在sharedPropertyDefinition后,进行监测;
createComputedGetter
- 缓存控制是通过watcher.dirty控制的,watcher.evaluate用来重新计算,更新缓存值,并重置dirty为false,表示缓存已更新
watcher.depend()
if (Dep.target) {
watcher.depend();
}
Watcher.prototype.depend = function() {
var i = this.deps.length;
while (i--) {
// this.deps[i].depend();
dep.addSub(Dep.target)
}
};
以上代码有个牵线的作用:
- P 引用了 C,C 引用了 D;
- 理论上 D 改变时, C 就会改变,C 则通知 P 更新;
- 实际上 C 让 D 和 P 建立联系,让 D 改变时直接通知 P;
Dep.target是什么
Dep.target是页面watcher
createGetterInvoker
如果没有缓存则直接执行computed的getter函数
相关面试题
- 如果计算属性c的取值为c = a+b,如果a=1,b=2;ab的值更新为a=2,b=1后,c的值重新计算还是从缓存中取?
vue系列课程
最近会陆续的对vue进行源码分析,一系列课程如下: