这一章就着重讲两个点:
响应式系统如何收集依赖
响应式系统如何更新视图
我们知道通过Object.defineProperty
做了数据劫持,当数据改变的时候,get
方法收集依赖,进而set
方法调用dep.notify
方法去通知Watcher
调用本身update
方法去更新视图。那么我们抛开其他问题,就讨论get
,notify
,update
等方法,直接上代码:
get( )
get: function reactiveGetter () {const value = getter ? getter.call(obj) : valif (Dep.target) {dep.depend()if (childOb) {childOb.dep.depend()if (Array.isArray(value)) {dependArray(value)}}}return value}
我们知道Dep.target
在创建Watcher
的时候是null
,并且它只是起到一个标记的作用,当我们创建Watcher
实例的时候,我们的Dep.target
就会被赋值到Watcher
实例,进而放入target
栈中,我们这里调用的是pushTarget
函数:
// 将watcher实例赋值给Dep.target,用于依赖收集。同时将该实例存入target栈中
export function pushTarget (_target: ?Watcher) {if (Dep.target) targetStack.push(Dep.target)Dep.target = _target
}
那我们继续执行到if (Dep.target)
语句的时候就会调用Dep.depend
函数:
// 将自身加入到全局的watcher中depend () {if (Dep.target) {Dep.target.addDep(this)}}
那下面的childOb
是啥东西呢?
let childOb = !shallow && observe(val)
我们通过这个变量判断当前属性下面是否还有ob
属性,如果有的话继续调用Dep.depend
函数,没有的话则不处理。 我们还需要处理当前传入的value
类型,是数组属性的话则会调用dependArray
收集数组依赖
// 收集数组依赖
function dependArray (value: Array<any>) {
for (let e, i = 0, l = value.length; i < l; i++) {e = value[i]e && e.__ob__ && e.__ob__.dep.depend()if (Array.isArray(e)) {dependArray(e)}
}
}
那么收集依赖部分
到这里就完了现在进行下一步触发更新
了
set( )
set: function reactiveSetter (newVal) {const value = getter ? getter.call(obj) : val/* eslint-disable no-self-compare */// 判断NaN的情况if (newVal === value || (newVal !== newVal && value !== value)) {return}/* eslint-enable no-self-compare */if (process.env.NODE_ENV !== 'production' && customSetter) {customSette