內文寫在註解
// src/core/observer/index.js
/*********************************************************
Observer 是一個 class,
作用是給物件的所有屬性加上 getters 和 setter
**********************************************************/
export class Observer {
value: any;
dep: Dep;
vmCount: number;
constructor (value: any) {
this.value = value
this.dep = new Dep()
this.vmCount = 0
/*************************************************
執行 def 把自身實例加到數據對象的 value 的 _ob_ 屬性上
def function 是 Object.defineProperty 的封裝
**************************************************/
def(value, '__ob__', this)
if (Array.isArray(value)) {
const augment = hasProto
? protoAugment
: copyAugment
augment(value, arrayMethods, arrayKeys)
this.observeArray(value)
} else {
this.walk(value)
}
}
/*************************************************
在元件中我們定義了 data 有哪些屬性,
defineReactive 給物件的所有屬性加上 getters 和 setter
**************************************************/
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
//...
}
/*********************************************************
observe 用來監測數據的變化,給非 VNode 物件加上 Observer
**********************************************************/
export function observe (value: any, asRootData: ?boolean): Observer | void {
if (!isObject(value) || value instanceof VNode) {
return
}
let ob: Observer | void
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
shouldObserve &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value)
}
if (asRootData && ob) {
ob.vmCount++
}
return ob
}
// src/core/util/lang.js
/*************************************************
def function 是 Object.defineProperty 的封裝,
若印出 data 上物件類型的數據,會看到該物件有 _ob_ 屬性
**************************************************/
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}