keep-alive

keep-alive


①概念:

            keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们

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

②作用:

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

③参数:

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

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

 原理:

 Vue 的缓存机制并不是直接存储 DOM 结构,而是将 DOM 节点抽象成了一个个 VNode节点,因此,Vue 的 keep-alive 缓存也是基于 VNode节点 而不是直接存储 DOM 节点。

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

 ④生命周期:

  被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated(组件激活时使用) 与 deactivated(组件离开时调用);

正常生命周期:beforeRouteEnter --> created --> mounted --> updated -->destroyed

使用keepAlive后生命周期:
首次进入缓存页面:beforeRouteEnter --> created --> mounted --> activated --> deactivated
再次进入缓存页面:beforeRouteEnter --> activated --> deactivated

注:
1、这里的activated非常有用,因为页面被缓存时,created,mounted等生命周期均失效,你若想进行一些操作,那么可以在activated内完成(下面会举个栗子:列表页回到上次浏览位置)
2、activated   keep-alive组件激活时调用,该钩子在服务器端渲染期间不被调用。 
3、deactivated   keep-alive组件停用时调用,该钩子在服务端渲染期间不被调用。
​

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]);
 
  }
 
}

​

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值