getter
且不存在 setter
的情况下,不会获取 key
的数据对象,此时 val
为 undefined
,之后调用 observe
时将不对其进行深度观察。正如之后的 setter
访问器中的:
if (getter && !setter) return
此时数据将是只读状态,既然是只读状态,则不存在数据修改问题,继而无须深度观察数据以便在数据变化时调用观察者注册的方法。
Observe
在 defineReactive
里,我们先获取了 target[key]
的 descriptor
,并缓存了对应的 getter
和 setter
,之后根据判断选择是否获取 target[key]
对应的 val
,接着是
let childOb = !shallow && observe(val)
根据 shallow
标志来确定是否调用 observe
,我们来看下 observe
函数:
// src/core/observer/index.js export function observe (value, asRootData) { if (!isObject(value) || value instanceof VNode) { return } let ob 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 }
首先判断需要观察的数据是否为对象以便通过 Object.defineProperty
定义 __ob__
属性,同时需要 value
不属于 VNode
的实例( VNode
实例通过 Diff
补丁算法来实现实例对比并更新)。接着判断 value
是否已有 __ob__
,如果没有则进行后续判断:
- shouldObserve:全局开关标志,通过toggleObserving来修改。
- !isServerRendering():判断是否服务端渲染。
- (Array.isArray(value) || isPlainObject(value)):数组和纯对象时才允许添加__ob__进行观察。
- Object.isExtensible(value):判断value是否可扩展。
- !value._isVue:避免Vue实例被观察
满足以上五个条件时,才会调用 ob = new Observer(value) ,接下来我们要看下 Observer 类里做了哪些工作
// src/core/observer/index.js export class Observer { constructor (value) { 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) { 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) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) } } }
内容版权声明:除非注明,否则皆为本站原创文章。