zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    IOS-多线程技术
    设计模式-抽象工厂设计模式
    IOS-内存管理
    IOS-MVC的使用
    POJ2411 Mondriaan's Dream (广场铺砖问题 状压dp)
    NOIp2006T2 金明的预算方案
    POJ1179 Polygon(区间DP)
    NOIp2006T1能量项链
    美梦1(JSOI2014SC)
    TJOI2013(BZOJ3173)最长上升子序列
  • 原文地址:https://www.cnblogs.com/vickylinj/p/14034909.html
Copyright © 2011-2022 走看看