不进行深度观测的我们在initRender函数中见过:
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => { !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm) }, true) defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => { !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm) }, true)
在Vue实例上定义属性$attrs和$listeners时就是非深度观测。
在get中收集依赖
接下来就是使用Object.defineProperty设置访问器属性,先看一下get函数:
get: function reactiveGetter () { const value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value },
get函数首先是要返回属性值,还有就是在这里收集依赖。
第一行代码就是获取属性值。先判断了getter是否存在,getter就是属性原有的get函数,如果存在的话调用该函数获取属性值,否则的话就用val作为属性值。
接下来是收集依赖的代码:
if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } }
首先判断Dep.target是否存在,Dep.target就是要收集的依赖,如果存在的话,执行if语句块内的代码。
dep.depend()dep对象的depend方法执行就是收集依赖。
然后判断了childOb是否存在,存在的话执行childOb.dep.depend(). 那么childOb的值是谁呢?
如果我们有个数据对象:
data = { a: { b: 1 } }
经过observe观测之后,添加__ob__属性,变成如下模样:
data = { a: { b: 1, __ob__: { value, dep, vmCount } }, __ob__: { value, dep, vmCount } }
对于属性a来说,childOb === data.a.__ob__, 所以childOb.dep.depend()就是data.a.__ob__.dep.depend()
在if语句里面又一个if判断:
if (Array.isArray(value)) { dependArray(value) }
如果属性值是数组,调用dependArray函数逐个触发数组元素的依赖收集
在set函数中触发依赖
set: function reactiveSetter (newVal) { const value = getter ? getter.call(obj) : val /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value)) { return } /* eslint-enable no-self-compare */ if (process.env.NODE_ENV !== 'production' && customSetter) { customSetter() } // #7981: for accessor properties without setter if (getter && !setter) return if (setter) { setter.call(obj, newVal) } else { val = newVal } childOb = !shallow && observe(newVal) dep.notify() }
内容版权声明:除非注明,否则皆为本站原创文章。