# keep-alive 组件的原理

# 含义

keep-alive组件是一个抽象组件,它自身不会渲染成DOM元素,也不会出现在父组件链中。

# props 参数

  • include: 定义缓存的白名单
  • exclude: 定义缓存的黑名单
  • max: 定义缓存组件的数量上限值,超出将移除较久没使用的(LRU的策略)

# 部分源码解析

  • abstract属性控制是否渲染成DOM元素
  • cache: 用来作为缓存容器,保存vnode节点
  • keys:存放已缓存的组件名(每次缓存组件被访问(或者新访问一个组件),就会把访问的放到尾部,这样比较少用的就在头部,结合max属性,把头部的优先移除掉)
// src/core/components/keep-alive.js
export default {
  name: 'keep-alive',
  abstract: true, // 判断当前组件虚拟dom是否渲染成真实dom的关键
  props: {
      include: patternTypes, // 缓存白名单
      exclude: patternTypes, // 缓存黑名单
      max: [String, Number] // 缓存的组件
  },
  created() {
     this.cache = Object.create(null) // 缓存虚拟dom
     this.keys = [] // 缓存的虚拟dom的键集合
  },
  /* destroyed钩子中销毁所有cache中的组件实例 */
  destroyed() {
    for (const key in this.cache) {
       // 删除所有的缓存
       pruneCacheEntry(this.cache, key, this.keys)
    }
  },
 mounted() {
   // 实时监听黑白名单的变动
   this.$watch('include', val => {
       pruneCache(this, name => matched(val, name))
   })
   this.$watch('exclude', val => {
       pruneCache(this, name => !matches(val, name))
   })
 },

 render() {
    /* 得到slot插槽中的第一个组件 */
    const vnode: VNode = getFirstComponentChild(this.$slots.default)
    const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
    if (componentOptions) {

    }
    return vnode
 }
}

# destroyed 生命周期

  • 不是简单的 this.cache=null, 而是遍历销毁所有的缓存组件
  • 内部会调用vm.$destroy(), 完全的销毁一个实例,清理它与其他实例的连接,解绑它的全部指令和事件监听器。
  • 会触发各个缓存组件的beforeDestroy和destroyed的钩子。

# 被缓存组件的生命周期

  • 第一次渲染就是 正常的生命周期,然后多一个 activateddeactivated钩子函数。

  • 保存的是 VNode

  • 通过 cache对象保存

  • render方法通过 $slots.default 来缓存对应的vnode虚拟Dom节点

最后一次修改时间: 9/28/2020, 11:37:23 AM