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


不进行深度观测的我们在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()
}

      

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

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