Vue理解系列一之keep-alive

131 阅读1分钟

keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

首先介绍下Vue的渲染过程: Vue的渲染是从render阶段开始的,而keep-alive的渲染是从vnode->patch阶段(构建虚拟DOM数并将虚拟DOM转换为真正的DOM节点的过程)的。

export default {
  name: 'keep-alive',
  abstract: true,

  props: {
    include: patternTypes,/*字符串或正则表达式。只有名称匹配的组件会被缓存*/
    exclude: patternTypes,/*字符串或正则表达式。任何名称匹配的组件都不会被缓存。*/
    max: [String, Number],/*数字。最多可以缓存多少组件实例。*/
  },
  created(){...},
  destroyed(){...},
  mounted(){...},
  render(){
      //获取默认插槽中的第一个组件节点
      const slot = this.$slots.default
      const vnode: VNode = getFirstComponentChild(slot)
      //获取该组件节点的componentOptions
      const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
      /*如果组件节点存在,获取该节点的名称,取值优先为组件name,如若不存在name则取tag。判断该节点名称在不在include||在exclude,就直接返回vnode*/
      if (componentOptions) {
      const name: ?string = getComponentName(componentOptions)
      const { include, exclude } = this
      if (
        // not included
        (include && (!name || !matches(include, name))) ||
        // excluded
        (exclude && name && matches(exclude, name))
      ) {
        return vnode
      }
      /*end*/
      
      /*重点*/
      const { cache, keys } = this
      const key: ?string = vnode.key == null //获取组件key值
        // same constructor may get registered as different local components
        // so cid alone is not enough (#3269)
        ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
        : vnode.key
        
        //如果存在缓存,直接从缓存中取vnode实例
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance
        //将其删除并添加在最后
        remove(keys, key)
        keys.push(key)
      } else {
      //如果不存在缓存,则对组件进行缓存
        cache[key] = vnode
        keys.push(key)
        // 如果配置了max并且超过max,则从缓存中删除第一个
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
      }
      //最后设置keepAlive
      vnode.data.keepAlive = true
    }
    return vnode || (slot && slot[0])
  }
 }

在这里可以看出了keep-alive是名为keep-alive的组件,定义了一个abstract属性并赋值为true,这是为了定义它是一个抽象组件,它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。props属性:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。