Vue数据绑定简析小结(2)
首先初始化了一个 _watchers
数组,用来存放 watcher
,之后根据实例的 vm.$options
,相继调用 initProps
、 initMethods
、 initData
、 initComputed
和 initWatch
方法。
initProps
function initProps (vm, propsOptions) { const propsData = vm.$options.propsData || {} const props = vm._props = {} // cache prop keys so that future props updates can iterate using Array // instead of dynamic object key enumeration. const keys = vm.$options._propKeys = [] const isRoot = !vm.$parent // root instance props should be converted if (!isRoot) { toggleObserving(false) } for (const key in propsOptions) { keys.push(key) const value = validateProp(key, propsOptions, propsData, vm) ... defineReactive(props, key, value) if (!(key in vm)) { proxy(vm, '_props', key) } } toggleObserving(true) }
在这里, vm.$options.propsData
是通过父组件传给子组件实例的数据对象,如 <my-element :item="false"></my-element>
中的 {item: false}
,然后初始化 vm._props
和 vm.$options._propKeys
分别用来保存实例的 props
数据和 keys
,因为子组件中使用的是通过 proxy
引用的 _props
里的数据,而不是父组件传递的 propsData
,所以这里缓存了 _propKeys
,用来 updateChildComponent
时能更新 vm._props
。接着根据 isRoot
是否是根组件来判断是否需要调用 toggleObserving(false)
,这是一个全局的开关,来控制是否需要给对象添加 __ob__
属性。这个相信大家都不陌生,一般的组件的 data
等数据都包含这个属性,这里先不深究,等之后和 defineReactive
时一起讲解。因为 props
是通过父传给子的数据,在父元素 initState
时已经把 __ob__
添加上了,所以在不是实例化根组件时关闭了这个全局开关,待调用结束前在通过 toggleObserving(true)
开启。
之后是一个 for
循环,根据组件中定义的 propsOptions
对象来设置 vm._props
,这里的 propsOptions
就是我们常写的
export default { ... props: { item: { type: Object, default: () => ({}) } } }
循环体内,首先
const value = validateProp(key, propsOptions, propsData, vm)
validateProp
方法主要是校验数据是否符合我们定义的 type
,以及在 propsData
里未找到