vue源码阅读之Observer

vue源码阅读之Observer_第1张图片

我们上次学习了vue数据驱动的概念,以及简单的vue怎么知道数据更新,然后采取行动的。今天我们就来继续深入学习,vue怎么把数据和视图给绑定在一起的,数据发生变化,视图怎么会自动发生变化的。

vue中的Observer

之前讲了vue知道数据发生变化利用了Object.defineProperty函数,那么对于vue中定义的数据它是怎么把所有的数据给监听到呢。

这里就是Observer类做的事情,他会通过递归的方式把一个对象的所有属性都转化为可观测的对象。

首先Observer是一个类。

constructor (value: any) {
    this.value = value
    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)
    }
  }

有它的构造函数,每个要监听的属性值都会有自己的dep, this.dep = new Dep()也就是收集依赖存放的地方,然后为每个value定义了一个__ob__属性,它的值就是该Observer实例。这样就是为它打上标记,表示已经转化为响应式了,避免重复操作。

对于数组的响应式需要单独处理if (Array.isArray(value)),否则就是对象,采用this.walk(value)进行处理。

我们先看Object的情况walk怎么处理的

walk函数的实现

walk就是遍历完Object的所有的属性,把每个属性都转换成getter/setter的形式来侦测变化。

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

这是walk的实现,就是在遍历Object的每个属性,然后调用defineReactive函数来操作。如果传入的属性值还是一个Object的时候,会使用new Observer(val)来递归。

export function observe (value: any, asRootData: ?boolean): Observer | void {
  if (!isObject(value) || value instanceof VNode) {
    return
  }

在这段代码中实现的。

你可能感兴趣的:(vue.js,javascript,前端)