一步一步分析vue之observe

3,780 阅读2分钟

上一期,本我们讲了__data这个vue的属性是怎么一回事,本期,我们将用到vue的(2.5.9)版本,让我们了解一下observe 让我们看看observe都包含什么成员

observe = {
    value : "",
    dep : new Dep,
    vmCount : 0
}

那么 Dep 又是什么东西呢。

dep = {
    id : uid++,
    subs : []
}

好,让我们回到observe最开始出现的地方。在代码的3360行。

1
接着,按f11跟进去,我们可以看到,程序用new Observer(value)初始化了value,如下图所示。
2
接着按f11跟进去,我们看看初始化Observer做了些什么事情?
3
我们可以看到在程序的874行,用def(value, '__ob__', this);,用def对value和__Observer__进行处理。不用说,这肯定不是函数式的了 = =。让我们继续跟进去,看看def对value做了什么事情?按f11跟进去,如下图所示。
4
可以看到,不出所料,又是用了Object.defineProperty给这个value定义了一个 __ob__ 这个属性。这个属性在分析__data章节里给了个可以查阅的链接。但是,重点的是:我们知道,在代码的initData函数里,data=_data,而__ob__的value又被定义为value,也就是data,所以如果_data的值发生改变,data的值会发生变化,__ob__的值也会发生变化,会相应的触发getter/setter。调用完def这个函数,接下来该调用this.walk了,如下图。
5
this.walk接收的是一个刚刚赋值完__ob__属性的value属性。同样,让我们跟进去,看看究竟对value做了什么,如下图。
6
这里,obj即使我们刚才所传的value.可以看到,先用Object.keys取到的obj所有的key,然后用了一个for循环,对obj的每个key都调用defineReactive(obj, keys[i], obj[keys[i]]);,哈哈,既然它对每个keys[i],obj[keys[i]],都调用了这个defineReactive方法,我们不妨跟进去看看~~~。如下图。
7
哇!参数看着好高大上 = = 有木有 (先写这些,剩下的等明天再写。)
继续, 现在是2017年12月11日20:29:17
defineReactive这个函数的大致意思就是为我们$options里面的data,也就是说 __data(因为讲_data那期已经提过了,有一处代码是data = _data)的key定义setter/getter方法。
我们先来看看代码的979行,即var childOb = !shallow && observe(val);.这句话适用于当你的data里key对应的值是对象的情况下,就会递归地进行observe了。不知道的童鞋可以运行到此处然后f11进去看看。好,我们来看看他的get/set方法~写在注视里了

get

 get: function reactiveGetter () {
      var value = getter ? getter.call(obj) : val;//先看看有没默认的get方法,没有就用val,即当初传进来的值
      if (Dep.target) {//这个以后在分析
        dep.depend();
        if (childOb) {
          childOb.dep.depend();
          if (Array.isArray(value)) {
            dependArray(value);
          }
        }
      }
      return value
    }

set

set: function reactiveSetter (newVal) {
      var value = getter ? getter.call(obj) : val;//先看看有没默认的get方法,没有就用val,即当初传进来的值
      /* eslint-disable no-self-compare */
      //如果新值等于旧值,就不触发视图更新等操作了。
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if ("development" !== 'production' && customSetter) {
        customSetter();
      }
      //如果有默认set方法就用默认的,否则新值赋给旧值。
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      //重新生成一下childOb 处理 字符串变为对象 或者 对象变为字符串 等情况。
      childOb = !shallow && observe(newVal);
      //notify 触发视图更新操作。
      dep.notify();
    }

好了,observe分析的差不多了。下一步我们该分析$mount了。