VUE2.6.10——computed计算属性

computed初始化

在实例化Vue对象得时候,我们通过computed来定义计算属性:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter  
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
})

在实例化时,初始化计算属性initComputed(源码路径/src/core/instance/state.js)

for (const key in computed) {
    const userDef = computed[key]
    const getter = typeof userDef === 'function' ? userDef : userDef.get
    ....
    //定义Watcher
    vm._computedWatchers[key] = new Watcher({
        vm,
        getter || noop, 
        noop,
        { lazy: true } //调用时才计算属性的值
    })
    //
    defineComputed(vm, key, userDef)
}

在defineComputed重新定义属性

Object.defineProperty(vm, key, {
    get : function(){
        const watcher = this._computedWatchers && this._computedWatchers[key]
        if (watcher) {
          if (watcher.dirty) { //this.dirty = this.lazy
            watcher.evaluate() //调用get设置watcher.value的值
          }
          if (Dep.target) { 
            watcher.depend()
          }
          return watcher.value
        }
    }
})

总结初始化流程如下:

  • 为每个计算属性初始化一个Watcher对象,保存在实例得_computedWatchers变量中
  • 重新定义计算属性得get属性,从Watcher中获取返回属性的值。

Watcher

  evaluate () {
    this.value = this.get()
    this.dirty = false
  }

  get () {
    pushTarget(this)
    let value
    const vm = this.vm
    try {
      value = this.getter.call(vm, vm)  //getter为key对应的函数,执行话术获取值
    } catch (e) {
      if (this.user) {
        handleError(e, vm, `getter for watcher "${this.expression}"`)
      } else {
        throw e
      }
    } finally {
      if (this.deep) {
        traverse(value)
      }
      popTarget()
      this.cleanupDeps()
    }
    return value
  }

你可能感兴趣的:(vue.js,源码分析)