keep-alive

概念

keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。

 

作用

在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间,提高用户体验性 

 

参数

  Keep-alive 组件提供了 include 和 exclude 两个属性,允许组件有条件的进行缓存。 

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

 

原理

  Vue 的缓存机制并不是直接存储 DOM 结构,而是将 DOM 节点抽象成了一个个 VNode节点

  因此,Vue 的 keep-alive 缓存也是基于 VNode节点 而不是直接存储 DOM 节点。

   VNode:虚拟DOM,其实就是一个JS对象 

 

生命钩子函数(如果不使用 keep-alive,生命钩子函数不存在)

  Keep-alive 组件提供了两个生命钩子函数,分别是 activated 和 deactivated 。

       1.activated 

当页面存在缓存的时候执行该函数。

       2.deactivated 

在页面结束时触发该方法,可清除掉滚动方法等缓存。

如下:

export default {
 
  name: "keep-alive",
 
  abstract: true, // 抽象组件属性 ,它在组件实例建立父子关系的时候会被忽略,发生在 initLifecycle 的过程中
 
  props: {
 
    include: patternTypes, // 被缓存组件
 
    exclude: patternTypes, // 不被缓存组件
 
    max: [String, Number] // 指定缓存大小
 
  },
 
 
 
  created() {
 
    this.cache = Object.create(null); // 缓存
 
    this.keys = []; // 缓存的VNode的键
 
  },
 
 
 
  destroyed() {
 
    for (const key in this.cache) {
 
      // 删除所有缓存
 
      pruneCacheEntry(this.cache, key, this.keys);
 
    }
 
  },
 
 
 
  mounted() {
 
    // 监听缓存/不缓存组件
 
    this.$watch("include", val => {
 
      pruneCache(this, name => matches(val, name));
 
    });
 
    this.$watch("exclude", val => {
 
      pruneCache(this, name => !matches(val, name));
 
    });
 
  },
 
 
 
  render() {
 
    // 获取第一个子元素的 vnode
 
    const slot = this.$slots.default;
 
    const vnode: VNode = getFirstComponentChild(slot);
 
    const componentOptions: ?VNodeComponentOptions =
 
      vnode && vnode.componentOptions;
 
    if (componentOptions) {
 
      // name不在inlcude中或者在exlude中 直接返回vnode
 
      // check pattern
 
      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;
 
      }
 
 
 
      const { cache, keys } = this;
 
      // 获取键,优先获取组件的name字段,否则是组件的tag
 
      const key: ?string =
 
        vnode.key == null
 
          ? // 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 的组件实例,并且重新调整了 key 的顺序放在了最后一个
 
      if (cache[key]) {
 
        vnode.componentInstance = cache[key].componentInstance;
 
        // make current key freshest
 
        remove(keys, key);
 
        keys.push(key);
 
      }
 
      // 不命中缓存,把 vnode 设置进缓存
 
      else {
 
        cache[key] = vnode;
 
        keys.push(key);
 
        // prune oldest entry
 
        // 如果配置了 max 并且缓存的长度超过了 this.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]);
 
  }
 
}

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值