很早就知道vue是通过Object.defineProperty实现响应式,但是一直对响应式得调用逻辑很模糊,自己看Watcher、Dep准是有一点似懂非懂,今天自己参考Vue源码实现了简化版的响应式。
- 以Vue单个组件渲染过程为例,Vue首先会实例化一个watcher对象(渲染watcher),然后将组件中data函数返回的数据进行响应式处理(调用函数defineReactive() ),响应式处理函数如下图(超简化版):
- defineReactive函数中实例化一个Dep,dep中有一个容器,用来存放所有依赖或者说订阅该属性的watcher,数据响应式以后,DOM渲染时有使用data数据(实际是使用响应式以后挂载到this.data对象中的属性即a或者b)就会触发get,触发get以后会调用dep.depend()。 dep.js如下图:
- dep.depend()函数执行Dep.target.addDep(this), 此时Dep.target就是组件渲染时创建的watcher实例,即调用watcher实例中的addDep方法。 watcher.js如下图:
- 很显然,该属性被访问说明DOM渲染中会使用到这个属性,所以组件watcher会收集这个属性对应的dep,同时通知这个dep(通过dep.addSub())我要订阅,dep收到通知就会把watcher存到subs中。
- 当这个属性发生变化时,set会触发,并调用对应属性下的dep.notify,notify会遍历subs(此时subs中都是存着订阅该属性的watcher)。并调用所有订阅该属性watcher下的update方法