VUE props 实现原理(源码解析)

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对象是被赋值到了当前实例上的$optionspropsData属性中,那我们可以看一下初始化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)
    }
  }

总的来说,就是将父组件传给它的属性,定义到了它自己的实例上了。

你可能感兴趣的:(vue.js)