Vue数据绑定简析小结(3)

key 时,获取默认值并在对象上定义 __ob__ ,最后返回相应的值,在这里不做展开。

这里我们先跳过 defineReactive ,看最后

if (!(key in vm)) {
 proxy(vm, '_props', key)
}

其中 proxy 方法:

function proxy (target, sourceKey, key) {
 sharedPropertyDefinition.get = function proxyGetter () {
  return this[sourceKey][key]
 }
 sharedPropertyDefinition.set = function proxySetter (val) {
  this[sourceKey][key] = val
 }
 Object.defineProperty(target, key, sharedPropertyDefinition)
}

vm 不存在 key 属性时,通过 Object.defineProperty 使得我们能通过 vm[key] 访问到 vm._props[key]

defineReactive

initProps 中,我们了解到其首先根据用户定义的 vm.$options.props 对象,通过对父组件设置的传值对象 vm.$options.propsData 进行数据校验,返回有效值并保存到 vm._props ,同时保存相应的 keyvm.$options._propKeys 以便进行子组件的 props 数据更新,最后利用 getter/setter 存取器属性,将 vm[key] 指向对 vm._props[key] 的操作。但其中跳过了最重要的 defineReactive ,现在我们将通过阅读 defineReactive 源码,了解响应式数据背后的实现原理。

// src/core/observer/index.js
export function defineReactive (
 obj,
 key,
 val,
 customSetter,
 shallow
) {
 const dep = new Dep()

 const property = Object.getOwnPropertyDescriptor(obj, key)
 if (property && property.configurable === false) {
  return
 }

 // cater for pre-defined getter/setters
 const getter = property && property.get
 const setter = property && property.set
 if ((!getter || setter) && arguments.length === 2) {
  val = obj[key]
 }

 let childOb = !shallow && observe(val)
 ...
}

首先 const dep = new Dep() 实例化了一个 dep ,在这里利用闭包来定义一个依赖项,用以与特定的 key 相对应。因为其通过 Object.defineProperty 重写 target[key]getter/setter 来实现数据的响应式,因此需要先判断对象 keyconfigurable 属性。接着

if ((!getter || setter) && arguments.length === 2) {
  val = obj[key]
}

arguments.length === 2 意味着调用 defineReactive 时未传递 val 值,此时 valundefined ,而 !getter || setter 判断条件则表示如果在 property 存在

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

转载注明出处:http://www.heiqu.com/385.html