vue源码解析之computed原理

3,309 阅读2分钟

源码分析

initComputed

initComputed这段代码做了几件事

  1. 每个computed配发watcher;
  2. defineComputed处理;
  3. 收集所有computed的watcher;

watcher做了什么

看下Watcher源码构造函数

  1. computed新建watcher的时候,传入lazy,作用是把计算结果缓存起来,而不是每次使用都要重新计算;
  2. 保存设置的 getter,把用户设置的 computed-getter,存放到 watcher.getter 中,用于后面的计算;
  3. watcher.value 存放计算结果,但是这里有个条件,因为 lazy 的原因,不会新建实例并马上读取值;这里可以算是 Vue 的一个优化,只有你再读取 computed,再开始计算,而不是初始化就开始计算值了,虽然没有一开始计算,但是计算 value 还是这个 watcher.get 这个方法;

defineComputed 处理

  1. set函数默认是空函数,如果用户设置了,则使用用户设置;
  2. 如果使用缓存,则get方法通过createComputedGetter包装,否则用createGetterInvoker进行包装;
  3. 将set方法和get方法封装在sharedPropertyDefinition后,进行监测;

createComputedGetter

  1. 缓存控制是通过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)
    }
};

以上代码有个牵线的作用:

  1. P 引用了 C,C 引用了 D;
  2. 理论上 D 改变时, C 就会改变,C 则通知 P 更新;
  3. 实际上 C 让 D 和 P 建立联系,让 D 改变时直接通知 P;
Dep.target是什么

Dep.target是页面watcher

createGetterInvoker

如果没有缓存则直接执行computed的getter函数

相关面试题

  1. 如果计算属性c的取值为c = a+b,如果a=1,b=2;ab的值更新为a=2,b=1后,c的值重新计算还是从缓存中取?

vue系列课程

最近会陆续的对vue进行源码分析,一系列课程如下:

state系列

  1. props原理
  2. methods原理
  3. data原理
  4. computed原理
  5. watch原理

lifecycle系列

  1. 生命周期原理

event系列

  1. event原理

render系列

  1. render原理

inject/provide系列

  1. inject/provide原理

plugins系列

  1. vue-router原理
  2. Vue Router 那些事
  3. Vuex你应该知道的事
  4. vue源码解析之vuex原理
  5. Vue自定义插件

组件系列

  1. keep-alive原理
  2. Vue 单文件组件
  3. Vue组件间通信
  4. vue虚拟列表

指令系列

  1. Vue自定义指令
  2. vue源码解析之Directives原理

算法系列

  1. diff原理
  2. Vue编译器源码分析

异步任务

  1. vue源码解析之NextTick原理

其他

  1. vue单元测试
  2. Vue轮播组件
  3. 你不知道的vue那些事
  4. vue技巧大解密
  5. 面试-高级前端之VUE数据响应式实现