VUE props 实现原理(源码解析)
前言
咱们在应用组件的时候,都会给组件传入一些属性,然而在应用时,却只是关注了它传递数据的性能,没有想过它是怎么的一个原理,具体是怎么实现的。
其实咱们平时写进去的组件,实质上就是一个template
模板,而这个template
模板在vue
中,会通过render
函数解析,最终生成一个VNode
。那咱们通过源码来看一下在生成VNode
后,组件属性是怎么实现传递的。
源码解析
生成虚构节点源码
在生成虚构节点这,咱们能够看到这样一段代码,而这段代码中,propsData
则是所有属性的一个定义,而这个对象的放在了虚构节点上,那咱们能够看看组件初始化时,这个propsData
对象经验了怎么的操作。
const vnode = new VNode( `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`, data, undefined, undefined, undefined, context, { Ctor, propsData, listeners, tag, children }, asyncFactory )
组件初始化源码
在下段代码中,咱们能够看到propsData
对象是被赋值到了以后实例上的$options
的propsData
属性中,那咱们能够看一下初始化props
时,这个propsData
对象又通过了怎么的一个过程。
const opts = vm.$options = Object.create(vm.constructor.options)、 const parentVnode = options._parentVnode opts._parentVnode = parentVnode const vnodeComponentOptions = parentVnode.componentOptions opts.propsData = vnodeComponentOptions.propsData
初始化props
源码
在这里,从$options
拿到$options
对象后,申明了一个叫_props
的空对象。
const propsData = vm.$options.propsData || {} const props = vm._props = {}
上面通过vm.$parent
判断一下是不是根元素,如果是根元素,属性则须要设置为响应式的,如果不是则不须要。
const isRoot = !vm.$parent if (!isRoot) {//如果是根元素 属性须要定义成响应式 toggleObserving(false) }
循环用户定义了的propsOptions
选项,它会依据用户定义的对象来和用户传入的值通过validateProp
办法来进行一个校验,并且拿到最终的后果value
。
而后将以后key和value值,通过defineReactive
定义到咱们后面的_props
中。
最终,将_props
对象定义到咱们的实例下来,这样咱们就能够通过实例,间接拿取到属性了。
for (const key in propsOptions) { keys.push(key) //校验用户定义的属性和传入的属性 const value = validateProp(key, propsOptions, propsData, vm) if (process.env.NODE_ENV !== 'production') { } else { defineReactive(props, key, value) } if (!(key in vm)) { proxy(vm, `_props`, key) } }
总的来说,就是将父组件传给它的属性,定义到了它本人的实例上了。