vue源码分析(十一)核心函数之Observe

2020-04-21  本文已影响0人  vue爱好者

我们打开文件 src/core/observer/index.js,找到定义Observer函数的代码:

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that have this object as root $data

  constructor (value: any) {
    this.value = value
    // 用来给数据添加Dep依赖
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
    if (Array.isArray(value)) {
      if (hasProto) {
        protoAugment(value, arrayMethods)
      } else {
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  /**
   * Walk through all properties and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

  /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

constructor

constructor (value: any) {
    this.value = value
    // 用来给数据添加Dep依赖
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
    if (Array.isArray(value)) {
      if (hasProto) {
        protoAugment(value, arrayMethods)
      } else {
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

首先是给 value 对象添加了 'ob'属性。
然后判断value是否是数组,如果是数组的话,就对数组进行处理,然后在调用observeArray函数对value进行处理。

arrayMethods有如下具体方法,这些方法就是vue给我们实现了双向绑定[ 'push','pop', 'shift', 'unshift', 'splice','sort', 'reverse']

observeArray代码如下:

 /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

可以看到对数组进行了遍历监听,这就是为什么Object.defineProperty是不支持数组监听的,但是vue里面数组的改变还是一个响应式的特性。

接下来我们看看walk的代码,比较简单。

 walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

可以看到首先是获取了所有的keys,然后一一进行监听。

上一篇下一篇

猜你喜欢

热点阅读