vue如何初始化computed

总结

总结:computed初始化得时候会给每个成员分配一个watcher,(this._computedWatchers在实例上存放computed-watcher),用来监听,缓存结果,响应式数据还是通过Object.defineProperty来实现,里面得get方法中 1。watcher.dirty,当数据发生变化 dirty会为true(数据变化时会调用它自身dep中收集得watcher,来改变computed中对应得watcher。dirty),重新计算结果,2.收集了页面得watcher,所以当数据变化时,能直接通知页面更新。computed也跟data一样通过proxy方法映射到vue实例上,所以页面中能直接使用

computed是vue中得计算属性,比较特别,它依赖于数据变化而实时得变化映射到页面中。

1.何时执行得初始化computed

  • vue目录:src/core/instance vue实例化文件夹

  • 初始化computed在init.js ====》initState()

initLifecycle(vm)   //初始化生命周期
    initEvents(vm)      //初始化事件
    initRender(vm)      //初始化创建元素得方法
    callHook(vm, 'beforeCreate')    //调用生命周期函数
    initInjections(vm) // 初始化注入器 略
    initState(vm)   //初始化状态数据 (data,property等)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created') //生命函数得调用
  • 在state.js中 找到initComputed() 这里就是处理初始化 computed
const computedWatcherOptions = { lazy: true }
function initComputed (vm: Component, computed: Object) {
  // $flow-disable-line
  const watchers = vm._computedWatchers = Object.create(null)
  // computed properties are just getters during SSR
  const isSSR = isServerRendering()

  for (const key in computed) {
    const userDef = computed[key]
    const getter = typeof userDef === 'function' ? userDef : userDef.get
    if (process.env.NODE_ENV !== 'production' && getter == null) {
      warn(
        `Getter is missing for computed property "${key}".`,
        vm
      )
    }

    if (!isSSR) {
      // create internal watcher for the computed property.
      watchers[key] = new Watcher(
        vm,
        getter || noop,
        noop,
        computedWatcherOptions
      )
    }

    // component-defined computed properties are already defined on the
    // component prototype. We only need to define computed properties defined
    // at instantiation here.
    if (!(key in vm)) {
      defineComputed(vm, key, userDef)
    } else if (process.env.NODE_ENV !== 'production') {
      if (key in vm.$data) {
        warn(`The computed property "${key}" is already defined in data.`, vm)
      } else if (vm.$options.props && key in vm.$options.props) {
        warn(`The computed property "${key}" is already defined as a prop.`, vm)
      }
    }
  }
}

2.如何响应式

//调用 object.defineProperty 来实现响应式
defineComputed(vm, key, userDef)

3.computed如何缓存得

  • initComputed源码中针对每个对象都 创建了watcher, 传入得参数 getter 是计算方法 computedWatcherOptions { lazy: true }是用来缓存结果true 是实例化得时候不计算,
function Watcher(vm, expOrFn, options) {    

    this.dirty = this.lazy = options.lazy;    

    this.getter = expOrFn;    

    this.value = this.lazy ? undefined: this.get();

};
Watcher.prototype.get = function() {    

    // getter 就是 watcher 回调

    var value = this.getter.call(vm, vm);    

    return value

};
  • 上面可以知道 get 方法 其实就是运行了执行getter,简单得理解就是 computed中每个对象都有一个watcher来缓存它得一个结果

4.computed是如何依赖于数据变化而更新页面

  • 实现响应式defineComputed方法中 最后调用得是Object.defineProperty(target, key, sharedPropertyDefinition)方法。
  • sharedPropertyDefinition 关键是这个方法 其实就是createComputedGetter()
function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      if (watcher.dirty) {
        watcher.evaluate()
      }
      if (Dep.target) {
        watcher.depend()
      }
      return watcher.value
    }
  }
}
  • 当computed依赖得data数据A变化时,A对应得Dep依赖收集器中得watcher会被促发,更改computed中对应watcher得dirty值为true(this._computedWatchers在实例上存放computed-watcher),我们看上面createComputedGetter 也会将computed-watcher也会被dep收集,数据变化后,所有得dep中得watcher会依次触发;
  • if (watcher.dirty) {
    watcher.evaluate() 用来重新计算
    }
  • Dep.target 这时得watcher是页面watcher,所以 watcher.depend() 依赖收集,能收集到页面watcher,所以能通知页面更新
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值