入口
// 类似于工厂函数,在满足一定情况后会 new Observer(value),使得 value 具备响应式,同时返回 observer 实例
// 基本类型的值是没有 Observer 的
// asRootData 主要用于 vmCount 计算
export function observe (value: any, asRootData: ?boolean): Observer | void {
// 如果传入的值不是对象或者是 VNode 则直接返回
if (!isObject(value) || value instanceof VNode) {
return
}
let ob: Observer | void
// 如果已经观测过了则不再 new 一个新的
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
// 全局开关,在特定情况下不会对数据进行观测
shouldObserve &&
// 服务端渲染时,不会观测
!isServerRendering() &&
// 必须得是数据或者对象才对其观测
(Array.isArray(value) || isPlainObject(value)) &&
// 值必须得是可扩展的,Object.freeze/Object.preventExtensions/Object.seal 的值就不会对其的观测
Object.isExtensible(value) &&
// 防止 Vue 实例被观测
!value._isVue
) {
ob = new Observer(value)
}
//
if (asRootData && ob) {
ob.vmCount++
}
return ob
}
Observer
// 用于监听值
// value,值自身
// dep,观察值的依赖项集合
// vmCount,以当前值为 data option 的实例数量
// value.__ob__,definePrototype 实现的访问代理,指向当前 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
// 为数据自身添加一个访问代理,value.__ob__,将访问到当前 Observer 实例
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 (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
// 对数组的子集进行深度监听
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}