美文网首页
Vue computed 和 watcher

Vue computed 和 watcher

作者: _1633_ | 来源:发表于2020-12-10 23:39 被阅读0次

computed

    计算属性的初始化是发生在 Vue 实例初始化阶段的 initState 函数中     initComputed(vm, opts.computed);

    1. 创建 vm._computedWatchers 为⼀个空对象

    2.  遍历 computed,拿到计算属 性的每⼀个 userDef , 获取这个 userDef 对应的 getter 函数;

    3. 为每⼀个 getter 创建⼀个 watcher ,这个 watcher 和渲染 watcher 不同,它是⼀个 computed watcher;

    4. 最后对判断如果 key 不是 vm 的属性,则调用  defineComputed(vm, key, userDef) ,否则判断计算属性对于的 key 是否 已经被 data 或者 prop 所占用,如果是的话则在开发环境报相应的警告。

    其中 const computedWatcherOptions = { lazy: true }

computed

    const sharedPropertyDefinition = {

          enumerable: true,

          configurable: true,

          get: noop,

          set: noop

}

defineComputed

     defineComputed 就是利用 Object.defineProperty 给计算属性对应的 key 值添加 getter 和 setter

    createComputedGetterr 返回⼀个函数 computedGetter ,它就是计算属性对应的 getter。

createComputedGetter

    缓存: 在new Watcher时传入的第四个参数 computedWatcherOptions 的 lazy = true,对应就是watcher的构造函数中的 dirty 为true。在 computedGetter 中,如果 dirty 为 false(即依赖的值没有发生变化),就不会重新求值,相当于 computed 被缓存了

watcher

    计算属性的 watcher 和 普通 watcher 的不同

        在计算属性的 watcher 中, 传入的参数 computedWatcherOptions =  { lazy: true }, 所以它的 value = undefined,也不会调用 this.get() 方法

    1. 当我们在 首次渲染 render 的时候,访问到我们的计算属性的时候,就会触发 计算属性的 getter,就是 createComputedGetterr,然后会拿到 计算属性的 watcher  = this._computedWatchers && this._computedWatchers[key];

    如果 dirty 为 true ,就是要重新计算 watcher 的值,如果为false,那么就不用,就是使用缓存。

    if (watcher.dirty) {

        watcher.evaluate();

      }

evaluate

    2. evaluate 就会调用 get 方法,紧接着调用 this.getter.call(vm, vm), 也就是我们的 computed 的表达式,比如 

    name(){  return   this.count + 1 };

    3. 紧接着就会获取 this.count 的 值,也就是调用 count 的 getter 方法,并把  computed watcher 添加到 subs 中, 最后 return value 拿到计算属性的值, 然后 popTatget, 退出当前的 computed watcher。

    4.  if (Dep.target) { watcher.depend() }

     evaluate 执行完毕,如果Dep.target 为 true, 那么 此时的 Dep.target 为 渲染 Watcher,执行 depend。

    5 . 现在 count 收集了computed watcher 和 渲染 watcher, 当我们的依赖的数据 count 发生变化的时候,会触发 setter,就会 notify() 所有的 watcher,也包括我们的 computed watcher ,执行 update()。

update

    当依赖的值发生变化 update 时候,将 dirty = true ,那么就会 watcher.evaluate() 重新计算。


watcher

initWatch

   initWatch 对 watch 对象做遍历,拿到每⼀个 handler ,Vue 是支持 watch 的同⼀个 key 对应多个 handler ,所以如果 handler 是⼀个数组,则遍历这个数组,调用  createWatcher ⽅ 法,否则直接调用  createWatcher。

    createWatcher 拿到它最终的回调函数,最后调用 vm.$watch(keyOrFn, handler, options) 函数

    执行  var watcher = new Watcher(vm, expOrFn, cb, options), 实例化了⼀个 watcher,这是⼀个 user watcher ,因为 options.user = true。

    通过实例化 watcher 的方式,⼀旦我们 watch 的数据发送变化,它最终会执行  watcher 的 run 方法,执行回调函数 cb ,并且如果我们设置了 immediate 为 true,则直接会执行回调函数 cb 。最后返回了⼀个 unwatchFn 方法,它会调用  teardown 方法去移除这个 watcher 。

相关文章

网友评论

      本文标题:Vue computed 和 watcher

      本文链接:https://www.haomeiwen.com/subject/vjcesktx.html