Observer也定义在core/observer/index.js文件中,它是一个构造函数,用来将数据对象转换成响应式的。
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 {
this.walk(value)
}
}
/**
* Walk through all properties and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
/**
* Observe a list of Array items.
*/
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}
以上是Observer的全部代码,现在我们从constructor开始,来看一下实例化Observer都做了什么。
__ob__ 属性
constructor开始先初始化了几个实例属性
this.value = value this.dep = new Dep() this.vmCount = 0 def(value, '__ob__', this)
value就是实例化Observer时传递的参数,现在将它赋给了实例对象的value属性。dep属性指向实例化的Dep实例对象,它就是用来收集依赖的容器。vmCount属性被初始化为0.
接着使用def函数为数据对象添加了__ob__属性,它的值就是当前Observer实例对象。def定义在core/util/lang.js文件中,是对Object.defineProperty的封装。
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}
用def来定义__ob__属性是要把它定义成不可枚举的,这样遍历对象就不会遍历到它了。
假设我们的数据对象是
data = {
a: 1
}
添加__ob__属性后变成
data = {
a: 1,
__ob__: {
value: data, // data 数据对象本身
dep: new Dep(), // Dep实例
vmCount: 0
}
}
处理纯对象
接下来是一个if...else判断, 来区分数组和对象,因为对数组和对象的处理不同。
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods)
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
} else {
this.walk(value)
}
内容版权声明:除非注明,否则皆为本站原创文章。

