vue组件继承 通过keep-alive实现了解vue组件实现原理(1)

之前有一篇文章分析了作为一个文本节点,vue是如何进行挂载的。本次通过一个keep-alive的例子带大家来了解vue框架组件的实现原理。例子非常简单,页面长这个样子:

代码如下:

通过switch按钮来使动态组件在组件A和组件B中间切换,其中组件A是一个可以输入的输入框。在A和B中间切换的过程中,通过keep-alive组件可以保留输入的内容。

下面我们通过这个keep-alive组件是如何实现来了解vue的组件机制。以及当我们使用keep-alive的时候,应该注意哪些点。

在引入vue源码的时候,会为vue的原型引入一些原型方法,这些方法留待以后讲解。在new Vue的时候执行了vue这个构造函数,并且执行了_init方法。

可以在右侧看到new Vue时传入的options对象,其中components中包含的A和B组件也都是对象。在_init中对vm这个vue实例做了一系列的初始化以后,快要执行完_init时,通过vm.$mount来把实现把vm这个vue实例挂载到vm.$options.el即”#app”节点上:

由于是在运行时编译(生成render函数)的,上文的mount其实是先要生成render函数vue组件继承,再去调用通用的mount,由于通用的mount函数已经被缓存了,需要在当前实例的作用域下来调用,所以是通过call来调用,第一个参数为this。如下图:

在通用mount中调用mountComponent函数,先执行render函数获取vnode,然后返回vnode:

下面我们来看这里是如何生成vnode的vue组件继承,进入render函数后可以看到编译之后的render函数其实是长这个样子,当然为了便于查看,格式是调整过的:

(function anonymous({
  with(this){
    return _c(
      'div',
      {attrs:{"id":"app"}},
      [
        _c(
          'button',
          {on:{"click":change}},
          [_v("switch")]
        ),
        _v(" "),
        _c(
          'keep-alive',
          [
            _c(
              currentComp, 
              {tag:"component"}
            )
          ],
          1
        )
      ],
      1
    )}
  }
)

render函数会先从最里层开始生成vnode,在这里先来生成switch这个文本节点:

再把生成的vnode子节点作为参数传给上层,创建button节点:

在createElement函数中又调用了_createElement函数:

在_createElement中,判断button为保留标签,通过new VNode新建完vnode节点后返回:

接着对换行空白符实例化完了一个文本节点后,就对组件A开始构造vnode节点,调用_c函数:

这次在_createElement函数中,会通过resolveAsset方法,获取components中A组件的options对象,作为Ctor传入createComponent来构造vnode,data为构造vnode时需要的属性结构,context为当前上下文的vue实例:

在createComponent函数中,获取到vue构造函数后,通过extend方法得到组件A的构造函数:

之后在组件的占位节点上安装了钩子,在patch的时候才能体现用处,而下面的new Vnode是真正来实例化出vnode节点的,注意组件vnode中的tag格式比较特殊:

下面对A组件的上一层keepalive继续调用_createElement函数,由于keepalive为内置组件,所以走到了createComponent的逻辑:

可以注意一下children参数为上面构造出来的A组件的vnode:

在对keepalive标签调用createComponent时,还是使组建的构造函数继承了vue的构造函数:

在源码中,我们可以看到继承的逻辑如下,先是以Vue组件实例的原型为原型,赋给子组件初始化函数的原型。再把初始化函数挂到了子组件实例原型的构造函数上,这个逻辑在后面初始化子组件的时候会用到。

在createComponent中,接下来安装钩子和实例化vnode并返回,注意组件vnode下面children属性为undefined,但是componentOptions中有children属性:

vue 访问子组件_vue组件继承_vue子组件修改父组件

下面在render函数中走到了对div节点构造vnode了,由于是保留标签名,在_createElement中直接调用new VNode:

总体执行完render函数,即可得到tag为div的vnode,之后返回vnode:

———END———
限 时 特 惠:本站每日持续更新海量各大内部创业教程,一年会员只需128元,全站资源免费下载点击查看详情
站 长 微 信:jiumai99

滚动至顶部