美文网首页
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