vue2数据绑定以及收集依赖

1. Observer

主要是用来数据绑定,以及定义收集依赖的方法

数组: 重写原型上的方法,用来劫持数据的改变
对象:使用 defineProperty 来劫持数据,从而监听数据的改变和获取

2. Watcher

目标对象,所有监听的数据会生成一个 Watcher 实例,一 一对应。可以通过管理实例以及调用实例上的方法来更新页面

3. Dep

Watcher 依赖收集器 以及通知更新的喇叭,可以收集并管理 Watcher。他们之间的关系是多对多的,可以相互依赖更新

4. 收集依赖的时机以及过程

4.1. 收集依赖

vue2数据绑定以及收集依赖_第1张图片
initState 中会执行 observer, 劫持所有数据,封装一层方法,如下
vue2数据绑定以及收集依赖_第2张图片
注意,此时只是定义了 get 方法,并没有执行收集依赖的过程,所有此时还没有根据 data 建立 对应的 Watcher

4.2. 开始页面初始更新

vue2数据绑定以及收集依赖_第3张图片
里面主要会执行 mountComponent 方法
vue2数据绑定以及收集依赖_第4张图片

4.3. mountComponent 中收集依赖的细节

  1. 执行生命周期时,会实例化一个 Watcher 并且传入 updateComponent(更新页面的方法)
new Watcher(vm, updateComponent, noop, {
  before:function before () {
    if (vm._isMounted && !vm._isDestroyed) {
      callHook(vm, 'beforeUpdate');
    }
  }
}, true /* isRenderWatcher */);
  1. 随着实例初始化,将当前实例推入 Dep.target 中,并且执行 updateComponent
/**
 * Watcher 初始化时会执行一遍, 用来收集依赖以及获取 value 值
 */
get () {
  pushTarget(this)  // 等于 Dep.target = this, 这个很重要
  let value
  const vm = this.vm
  value = this.getter.call(vm, vm) // 执行 updateComponent 
  popTarget()   // 释放 Dep.target
  return value
}
  1. 执行 updateComponent 时,会触发 Observe 类中定义的 get(数据劫持) 方法
get: function reactiveGetter () {  // 每一个 data 都会执行一遍
  if (Dep.target) {  // 刚刚实例化 Watcher 时已经收集了 Dep.target
    dep.depend()     // 收集依赖
  }
},
  1. dep.depend() 收集依赖
depend() {
  if (Dep.target) {
    Dep.target.addDep(this)  // 调用 Wachter 实例上的 addDep 方法给 Watcher 添加 Deps
  }
}
  1. 调用 addDep 方法给 Watcher 添加 Deps
addDep (dep: Dep) {
  const id = dep.id
  if (!this.newDepIds.has(id)) {  // 不能重复录入
    this.newDepIds.add(id)        // 记录 dep 的身份标识
    this.newDeps.push(dep)
    if (!this.depIds.has(id)) {
      dep.addSub(this) // 将实例添加到 subs 数组中管理  === this.subs.push(Watcher)
    }
  }
}
  1. 依赖收集完毕
// Watcher
{
  deps: [
	watcher: {
	  subs: [
		//...	
	  ]
	}	
  ]
}

你可能感兴趣的:(Vue,javascript,vue,依赖收集)