入口
// 类似于工厂函数,在满足一定情况后会 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]) } }}