Vue 2.0的数据依赖实现原理代码简析(2)

export function validateProp ( key: string, propOptions: Object, // $options.props属性 propsData: Object, // $options.propsData属性 vm?: Component ): any { const prop = propOptions[key] // 如果在propsData测试props上没有缓存的key const absent = !hasOwn(propsData, key) let value = propsData[key] // 处理boolean类型的数据 // handle boolean props if (isType(Boolean, prop.type)) { if (absent && !hasOwn(prop, 'default')) { value = false } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) { value = true } } // check default value if (value === undefined) { // default属性值,是基本类型还是function // getPropsDefaultValue见下面第一段代码 value = getPropDefaultValue(vm, prop, key) // since the default value is a fresh copy, // make sure to observe it. const prevShouldConvert = observerState.shouldConvert observerState.shouldConvert = true // 将value的所有属性转化为getter/setter形式 // 并添加value的依赖 // observe方法的分析见下面第二段代码 observe(value) observerState.shouldConvert = prevShouldConvert } if (process.env.NODE_ENV !== 'production') { assertProp(prop, key, value, vm, absent) } return value }

// 获取prop的默认值 function getPropDefaultValue (vm: ?Component, prop: PropOptions, key: string): any { // no default, return undefined // 如果没有default属性的话,那么就返回undefined if (!hasOwn(prop, 'default')) { return undefined } const def = prop.default // the raw prop value was also undefined from previous render, // return previous default value to avoid unnecessary watcher trigger if (vm && vm.$options.propsData && vm.$options.propsData[key] === undefined && vm._props[key] !== undefined) { return vm._props[key] } // call factory function for non-Function types // a value is Function if its prototype is function even across different execution context // 如果是function 则调用def.call(vm) // 否则就返回default属性对应的值 return typeof def === 'function' && getType(prop.type) !== 'Function' ? def.call(vm) : def }

Vue提供了一个observe方法,在其内部实例化了一个Observer类,并返回Observer的实例。每一个Observer实例对应记录了props中这个的default value的所有依赖(仅限object类型),这个Observer实际上就是一个观察者,它维护了一个数组this.subs = []用以收集相关的subs(订阅者)(即这个观察者的依赖)。通过将default value转化为getter/setter形式,同时添加一个自定义__ob__属性,这个属性就对应Observer实例。

说起来有点绕,还是让我们看看我们给的demo里传入的options配置:

props: { a: { type: Object, default () { return { key1: 'a', key2: { a: 'b' } } } } }

在往上数的第二段代码里面的方法obervse(value),即对{key1: 'a', key2: {a: 'b'}}进行依赖的管理,同时将这个obj所有的属性值都转化为getter/setter形式。此外,Vue还会将props属性都代理到vm实例上,通过vm.key1,vm.key2就可以访问到这个属性。

此外,还需要了解下在Vue中管理依赖的一个非常重要的类: Dep

export default class Dep { constructor () { this.id = uid++ this.subs = [] } addSub () {...} // 添加订阅者(依赖) removeSub () {...} // 删除订阅者(依赖) depend () {...} // 检查当前Dep.target是否存在以及判断这个watcher已经被添加到了相应的依赖当中,如果没有则添加订阅者(依赖),如果已经被添加了那么就不做处理 notify () {...} // 通知订阅者(依赖)更新 }

在Vue的整个生命周期当中,你所定义的响应式的数据上都会绑定一个Dep实例去管理其依赖。它实际上就是观察者和订阅者联系的一个桥梁。

刚才谈到了对于依赖的管理,它的核心之一就是观察者Observer这个类:

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

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