Vue源码解析之数据响应系统的使用(6)


observe工厂函数

observe函数定义在core/observer/index.js文件中, 我们找到该函数的定义,一点点来看

if (!isObject(value) || value instanceof VNode) {
 return
}

首先判断如果数据不是一个对象或者是一个VNode实例,直接返回。

let ob: Observer | void

接着定义了ob变量,它是一个Observer实例,可以看到observe函数的最后返回了ob.

下面是一个if...else分支:

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分支,用hasOwn判断了数据对象是否包含__ob__属性,并且判断属性值是否是Observer的实例。如果条件为真的话,就把value.__ob__的值赋给ob。

为什么会有这个判断呢?每个数据对象被观测后都会在该对象上定义一个__ob__属性, 所以这个判断是为了防止重复观测一个对象。

接着是else if分支,这个条件判断有点多,我们一个个来看。

shouldObserve必须为true

该变量也定义在 core/observer/index.js 文件内,

/**
 * In some cases we may want to disable observation inside a component's
 * update computation.
 */
export let shouldObserve: boolean = true

export function toggleObserving (value: boolean) {
 shouldObserve = value
}

这段代码定义了shouldObserve变量,初始化为true。接着定义了toggleObserving函数,该函数接收一个参数,这个参数用来更新shouldObserve的值。shouldObserve为true时可以进行观测,为false时将不会进行观测。

!isServerRendering()必须为true

isServerRendering函数用来判断是否是服务端渲染,只有当不是服务端渲染的时候才会进行观测
(Array.isArray(value) || isPlainObject(value)) 必须为真

只有当数据对象是数组或者纯对象时才进行观测

Object.isExtensible(value)必须为true

被观测的数据对象必须是可扩展的, 普通对象默认就是可扩展当。以下三个方法可以将对象变得不可扩展:

Object.preventExtensions()、 Object.freeze()、Object.seal()

!value._isVue必须为真

Vue实例含有_isVue属性,这个判断是为了防止Vue实例被观测

以上条件满足之后,就会执行代码ob = new Observer(value),创建一个Observer实例

Observer 构造函数

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/19.html