Vue2源码【8-5】keep-alive

keep-alive是vue的内置组件,如果是用户想要自己实现一个类似keep-alive的组件是不可能的,因为需要vue的主干逻辑配合该组件的实现。

keep-alive的作用是缓存的是子组件的vnode,而其本身的render返回的也是vnode。

keep-alive的原理依赖slot的机制。

  • keep-alive表现出来的特点:
    • 它的作用就是缓存vnode!!!!!!!!!!!!!!!!!
    • 只处理第一个子节点
      • <keep-alive> 是用在其一个直属的子组件“被切换”的情形。
    • 易知其原理有一部分是基于slot等的原理
    • ( 是抽象组件 )
    • api
      • this.cachethis.keys:去缓存已经创建过的 vnode
      • props
        • include 和 exclude
        • 还定义了 max,它表示缓存的大小。因为我们是缓存的 vnode 对象,它也会持有 DOM,当我们缓存很多的时候,会比较占用内存,所以该配置允许我们指定缓存大小。

从用法可以看出,其原理无非就是对vnode数组的一些处理。这就不需要死记硬背其工作流程了。

【1】实际上,考虑了 MVVM“重新渲染”的过程中,需要重新执行keep-alive的逻辑。所以keep-alive有必要实现render函数,已实现更加复杂的函数逻辑。

  • <keep-alive> 作为组件配置options直接实现了 render 函数
    • 而不是我们常规的template模板描述视图的方式
    • 执行 <keep-alive> 组件渲染的时候,就会执行到这个 render 函数。

【2】另外一个特点就是依赖slot等等的机制来获取:这里面首次渲染和缓存渲染的逻辑是不一样的:

slot的首次渲染

对我们的例子,初始化渲染 A 组件以及第一次点击 switch 渲染 B 组件,都是首次渲染。

除了在 <keep-alive> 中建立缓存,和普通组件渲染没什么区别。

slot的缓存渲染

当我们从 B 组件再次点击 switch 切换到 A 组件,就会命中缓存渲染:

  • (keep-alive这个组件作为父组件)patch 走 patchVnode
    • prepatch 的钩子函数核心是 updateChildComponent
      • 需要对自己的 children,也就是这些 slots 做重新解析,
        • 并触发 <keep-alive> 组件实例 $forceUpdate 逻辑,也就是重新执行 <keep-alive>render 方法
        • 这个时候如果它包裹的第一个组件 vnode 命中缓存,则直接返回缓存中的 vnode.componentInstance
        • ( 在我们的例子中就是缓存的 A 组件 )
  • 接着又会执行 patch 过程,再次执行到 createComponent 方法
    • (这个时候 isReactivated 为 true,并且在执行 init 钩子函数的时候不会再执行组件的 mount 过程了。这也就是被 <keep-alive> 包裹的组件在有缓存的时候就不会在执行组件的 createdmounted 等钩子函数的原因了)
    • isReactivated 为 true 的情况下会执行 reactivateComponent 方法
      • 最后通过执行 insert(parentElm, vnode.elm, refElm) 就把缓存的 DOM 对象直接插入到目标元素中,完成渲染。

生命周期

上面过程大概解释了keep-alive运作过程中哪些生命周期钩子是否触发:

patch 过程中对于已缓存的组件不会执行 mounted,所以不会有一般的组件的生命周期函数但是又提供了 activateddeactivated 钩子函数。

文章目录
  1. slot的首次渲染
  2. slot的缓存渲染
  • 生命周期