首页 > 其他分享 >keep-alive

keep-alive

时间:2024-12-12 15:14:11浏览次数:2  
标签:缓存 name cache alive keep key 组件 vnode

keep-alive 是 Vue 的一个内置抽象组件,通常用于缓存动态组件或路由组件。

被 keep-alive 包裹的组件在切换时不会被销毁,而是会被缓存下来,下一次切换回这个组件时,会直接复用之前的实例,保持其状态。

keep-alive的几个配置属性和钩子:

1.include 和 exclude: 用于控制哪些组件需要缓存,支持字符串、正则表达式或数组。

2.max: 用于指定缓存的组件数量,当超出这个数量时,最久未使用的组件实例将被销毁。

3.activated:当组件被激活时触发(即从缓存中恢复时)。

4.deactivated:当组件被停用时触发(即被缓存时)。

 

keep-alive的核心原理:

keep-alive 是通过缓存组件实例来避免组件重复创建和销毁,达到性能优化的目的。它通过将已缓存的组件存储在内存中,当组件被重新激活时,直接复用之前缓存的实例,而不是重新创建。

核心原理步骤:

1.缓存实例:当组件被第一次加载时,keep-alive 会将组件的实例缓存起来。

2.组件复用:当你切换到一个已经被缓存的组件时,keep-alive 会从缓存中提取该组件的实例,而不是重新创建。

3.生命周期管理:为了处理组件的激活和停用,keep-alive 引入了 activateddeactivated 钩子,在组件进入或离开缓存时触发。

 

简单实现:

const KeepAlive = {
  name: 'keep-alive', // 定义组件的名字为 keep-alive
  abstract: true, // 将组件标记为抽象组件。抽象组件不会在父组件链中出现。

  props: {
    include: [String, RegExp, Array], // include:指定哪些组件需要被缓存,可以是字符串、正则表达式或数组。
    exclude: [String, RegExp, Array], // 指定哪些组件不需要被缓存,可以是字符串、正则表达式或数组
    max: [String, Number] // 缓存组件的最大数量
  },

  created() {
    this.cache = Object.create(null); // 用于存储缓存的组件实例。
    this.keys = []; // 用于存储缓存组件的键列表,按顺序保存。
  },

  destroyed() {
    for (const key in this.cache) {
      pruneCacheEntry(this.cache, key, this._vnode); // 遍历 this.cache 中的所有键,并调用 pruneCacheEntry 函数清理缓存
    }
  },

  mounted() {
    this.$watch('include', val => {
      pruneCache(this, name => matches(val, name)); // 监听 include 属性的变化,并调用 pruneCache 函数清理不匹配的缓存。
    });
    this.$watch('exclude', val => {
      pruneCache(this, name => !matches(val, name)); // 监听 exclude 属性的变化,并调用 pruneCache 函数清理匹配的缓存。
    });
  },

  render() { // 渲染函数,定义组件的渲染逻辑。
    const slot = this.$slots.default; // 获取默认插槽内容。
    const vnode = getFirstComponentChild(slot); // 获取插槽内容中的第一个子组件虚拟节点。
    const componentOptions = vnode && vnode.componentOptions; // 获取子组件的选项。

    if (componentOptions) { // 子组件的选项 存在时,继续处理。
      const name = getComponentName(componentOptions);
      const { include, exclude } = this;
      /**
       * 检查 include 和 exclude 属性。
       * 如果 include 存在且组件名称不匹配,则直接返回 vnode。
       * 如果 exclude 存在且组件名称匹配,则直接返回 vnode。
       */
      if (
        (include && (!name || !matches(include, name))) ||
        (exclude && name && matches(exclude, name))
      ) {
        return vnode;
      }
      /**
       * 生成缓存键 key。
       * 如果 vnode.key 为空,则使用组件构造函数的 cid 和标签名生成键。
       * 否则,使用 vnode.key 作为键。
       */
      const key = vnode.key == null
        ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
        : vnode.key;
      /**
       * 检查缓存中是否存在该键。
       * 如果存在,从缓存中取出组件实例,并将键移到 this.keys 的末尾。
       * 如果不存在,将组件虚拟节点存入缓存,并将键添加到 this.keys。
       * 如果缓存数量超过 max,则清理最早的缓存。
       */
      if (this.cache[key]) {
        vnode.componentInstance = this.cache[key].componentInstance;
        remove(this.keys, key);
        this.keys.push(key);
      } else {
        this.cache[key] = vnode;
        this.keys.push(key);
        if (this.max && this.keys.length > parseInt(this.max)) {
          pruneCacheEntry(this.cache, this.keys[0], this._vnode);
        }
      }

      vnode.data.keepAlive = true; // 标记虚拟节点为 keepAlive
    }

    return vnode || (slot && slot[0]); // 返回虚拟节点或插槽中的第一个子节点
  }
};
/**
 * 清理缓存条目。
 * 获取缓存条目 entry。
 * 如果存在且不等于当前虚拟节点,销毁组件实例。
 * 将缓存条目置为空。
 */
function pruneCacheEntry(cache, key, current) {
  const entry = cache[key];
  if (entry && (!current || entry.tag !== current.tag)) {
    entry.componentInstance.$destroy();
  }
  cache[key] = null;
}
/**
 * 根据过滤条件清理缓存。
 * 获取 cache、keys 和 _vnode。
 * 遍历缓存,获取组件名称。
 * 如果名称存在且不符合过滤条件,清理缓存条目。
 */
function pruneCache(keepAliveInstance, filter) {
  const { cache, keys, _vnode } = keepAliveInstance;
  for (const key in cache) {
    const entry = cache[key];
    if (entry) {
      const name = getComponentName(entry.componentOptions);
      if (name && !filter(name)) {
        pruneCacheEntry(cache, key, _vnode);
      }
    }
  }
}
/**
 * 检查名称是否匹配模式。
 * 如果模式是数组,检查名称是否在数组中。
 * 如果模式是字符串,拆分字符串并检查名称是否在其中。
 * 如果模式是正则表达式,测试名称是否匹配。
 * 否则返回 false。
 */
function matches(pattern, name) {
  if (Array.isArray(pattern)) {
    return pattern.indexOf(name) > -1;
  } else if (typeof pattern === 'string') {
    return pattern.split(',').indexOf(name) > -1;
  } else if (pattern.test) {
    return pattern.test(name);
  }
  return false;
}
// 获取组件构造函数的 name 或标签名
function getComponentName(opts) {
  return opts && (opts.Ctor.options.name || opts.tag);
}
// 获取第一个子组件 过滤并返回第一个有 componentOptions 的子节点。
function getFirstComponentChild(children) {
  return children && children.filter(c => c && c.componentOptions)[0];
}

ps: Vue 3 的 keep-alive 原理还是缓存组件实例

标签:缓存,name,cache,alive,keep,key,组件,vnode
From: https://www.cnblogs.com/ssszjh/p/18602526

相关文章

  • keepalived编译安装-CentOS X86
    环境信息操作系统:CentOSLinuxrelease7.9.2009(Core)架构:X86keepalived版本:2.3.1编译wgethttps://www.keepalived.org/software/keepalived-2.3.1.tar.gztarxvfkeepalived-2.3.1.tar.gzcdkeepalived-2.3.1/./configure--prefix=/usr/local/keepalivedmakema......
  • 【Zookeeper系列】常用指标采集 exporter
    #比较老旧不推荐https://github.com/dabealu/zookeeper-exporterhttps://github.com/carlpett/zookeeper_exporter/#jmx方式https://github.com/prometheus/jmx_exporter/blob/main/example_configs/zookeeper.yamlhttps://bbs.huaweicloud.com/blogs/166278为了更加方便的......
  • ZooKeeper可视化工具:提升分布式系统管理的效率
    ApacheZooKeeper是一个分布式协调服务,广泛应用于分布式系统中,用于维护配置信息、命名服务、提供分布式同步和组服务。然而,ZooKeeper的命令行接口虽然功能强大,但对于不熟悉命令行操作的用户来说,使用起来可能会有一定的门槛。为了提升ZooKeeper的管理效率和用户体验,许多开发者开发......
  • kube-apiserver 高可用,keepalived + haproxyNX
    作者:https://github.com/daemon365/p/18592136为什么要做高可用环境准备安装配置keepalived配置文件测试配置haproxy安装kubernetes集群测试:slowerssr加速器为什么要做高可用在生产环境中,kubernetes集群中会多多个master节点,每个master节点上都会部署......
  • kube-apiserver 高可用,keepalived + haproxy
    为什么要做高可用在生产环境中,kubernetes集群中会多多个master节点,每个master节点上都会部署kube-apiserver服务,实现高可用。但是client访问kube-apiserver时,需要指定ip或者域名,这样会出现单点故障。官方推荐的做法是使用一个负载均衡器,将多个kube-apiserver服务......
  • ZooKeeper最全详解 (万字图文总结!!!)
    目录一、什么是ZooKeeper1.1ZooKeeper的特点1.2ZooKeeper架构1.3ZooKeeper数据模型1.4数据节点类型二、Zookeeper安装2.1单机安装2.2集群安装2.3ZooKeeperACL使用2.4ZooKeeper使用场景2.5服务启动流程2.5.1单机启动2.5.2集群启动三、Zookeeper之ZAB......
  • Nginx高可用Keepalived
    1.Keepalived讲解高可用是指2台机器启动着完全相同的业务系统,一台机器宕机后,另一台可以快速启用,用户是无感知的。高可用硬件通常使用F5,软件通常使用keepalived。keepalived软件是基于VRRP协议实现的,VRRP虚拟路由冗余协议,主要用于解决单点故障。2.VRRP实现原理一般我们会选择......
  • ZooKeeper单机集群的安装
    下载地址https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/解压到指定目录tar-zxf/mnt/d/software/apache-zookeeper-3.8.4-bin.tar.gz-C/mnt/d/appsmv/mnt/d/apps/apache-zookeeper-3.8.4-bin/mnt/d/apps/zookeeper配置脚本#假设Zookeeper解压到以下目录ZK_H......
  • 题解:AT_abc382_d [ABC382D] Keep Distance
    题目传送门思路老样子,先看数据范围。\(2\leqN\leq12\)\(10N-9\leqM\leq10N\)加上限时五秒钟,所以可以放心的写。设\(X\)为输出的倒数第\(Y\)个数,\(Z\)为上一个数的值。观察样例,确定\(X\)的取值范围是\((Z+10)\sim(M-Y\times10+10)\)这样我们就可......
  • 将Linux内核参数ip_forward设置为0后,以下那些功能可能受影响:Nginx、LVS、Keepalived、
    将Linux内核参数ip_forward设置为0后,以下那些功能可能受影响:Nginx、LVS、Keepalived、iptables、firewalld、HAProxy将Linux内核参数ip_forward设置为0后,影响的是系统的IP数据包转发功能。它决定了Linux是否能够作为路由器转发非本机目标的数据包。当其值为0时,系......