Observer
export class Observer {
value: any;
dep: Dep;
vmCount: number; // number of vms that have this object as root $data
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 {
}
}
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}
observer类中如果是数组,则会先劫持数组的原型,对数组原型进行改造。然后再通过observeArray方法去循环调用observe方法。使数组中的每一项都被侦测。
数组原型劫持
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
methodsToPatch.forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
ob.dep.notify()
return result
})
})
通过Object.create继承数组的原型得到arrayMethods,然后对数组的7个方法进行重写并添加到arrayMethods的原型上。
先保存一份原来的数组方法,并获取原来数组方法的返回值。然后重写方法。对于push,unshift,splice有插入值操作的方法,会对插入的值继续通过observeArray侦测。然后获取数组的响应式标记__ob__,即observer类。因为observer类也有dep实例,所以通过this.ob.dep.notify()去派发更新。最后返回原先数组方法的返回值。
protoAugment和copyAugment
protoAugment中将数组的__proto__指向新的原型对象。 如果不兼容的情况下可以使用copyAugment,将每一项手动添加到数组新原型。
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)
}
}
}
在defineReactive中对于value是数组的单独处理。循环数组,对于数组的每一项进行收集依赖。