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

  }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值