• 【Vue】watch中的deep:true源码实现


    当用户指定了watch中的deep属性为true时,如果当时监控的属性是数组类型,会对对象中的每一项进行求值,此时会将当前watcher存入到对应属性的依赖中,这样数组中对象发生变化时也会通知数据更新。内部原理就是递归,耗费性能 。

    整体流程: 

    initWatch 初期化user watcher(1),user watcher在defineReactive的get中订阅属性的变化(2),在defineReactive的set时触发notify(2),notify调用每个订阅了改属性变化的watcher的update(3),监听 watcher 进入update的queueWatcher,在queueWatcher的nextTick中调用flushSchedulerQueue(4),flushSchedulerQueue中调用监听watcher的run(5),在watcher.run中调用this.get,在this.get中判断this.deep是否为true,为true则执行traverse,在traverse中会因为对属性的取值触发2的get方法,并且traverse递归调用,使当前watch监听到对象内部的每一个属性(6),进而调用用户在watch属性上定义的方法。 

    1、initWatch 初期化user watcher(srccoreinstancestate.js) 

    function initWatch (vm: Component, watch: Object) {
      for (const key in watch) {
        const handler = watch[key]
        if (Array.isArray(handler)) {
          for (let i = 0; i < handler.length; i++) {
            createWatcher(vm, key, handler[i])//每一项创建一个watcher
          }
        } else {
          createWatcher(vm, key, handler)
        }
      }
    }

    2、user watcher在defineReactive的get中订阅属性的变化,在defineReactive的set时触发notify

    export function defineReactive (
      obj: Object,
      key: string,
      val: any,
      customSetter?: ?Function,
      shallow?: boolean
    ) {
      ...
      Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter () {
          const value = getter ? getter.call(obj) : val
          if (Dep.target) {
            dep.depend()
            if (childOb) {
              childOb.dep.depend()
              if (Array.isArray(value)) {
                dependArray(value)
              }
            }
          }
          return value
        },
        set: function reactiveSetter (newVal) {
          ...
          dep.notify()
        }
      })
    }

    3、notify调用每个订阅了改属性变化的watcher的update

    notify () {
        ...
        for (let i = 0, l = subs.length; i < l; i++) {
          subs[i].update()
        }
      }

    4、queueWatcher(srccoreobserverscheduler.js): 

    export function queueWatcher (watcher: Watcher) {
       ...
       nextTick(flushSchedulerQueue)
    }

    5、调用监听watcher的run

    function flushSchedulerQueue () {
      ...
      for (index = 0; index < queue.length; index++) {
      ...
        watcher.run()
      ...
       }
      ...    
    }

    6、traverse

  • 相关阅读:
    python+fiddler 抓取抖音数据包并下载抖音视频
    fiddler抓包+安卓机 完成手机app抓包的配置 遇到的一些问题
    Mobileye独创性创新
    EyeQ进展The Evolution of EyeQ
    Mobileye高级驾驶辅助系统(ADAS)
    重型车辆盲区行为检查Behaviours – Heavy Vehicle Blind Spots
    Xilinx低比特率高品质 ABR 视频实时转码(HPE 参考架构)
    Xilinx FPGA全局介绍
    用NumPy genfromtxt导入数据
    如何在Python中加速信号处理
  • 原文地址:https://www.cnblogs.com/vickylinj/p/14034909.html
Copyright © 2020-2023  润新知