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])
}
}
}
内容版权声明:除非注明,否则皆为本站原创文章。
