当前位置: 首页 > article >正文

Vue3 keep-alive核心源码的解析

在 Vue 3 中,<keep-alive> 组件的源码实现比较复杂,但主要涉及的是组件实例的缓存、生命周期钩子的管理、以及缓存策略。以下是对其核心源码的解析。

1. KeepAlive 的核心结构

<keep-alive> 组件的核心在于它如何管理组件实例的缓存,以及如何在组件被复用和销毁之间做切换。以下是 KeepAlive 的基本实现结构。

export const KeepAlive = {
  name: 'KeepAlive',
  __isKeepAlive: true, // 标识为 KeepAlive 组件

  props: {
    include: [String, RegExp, Array],
    exclude: [String, RegExp, Array],
    max: [String, Number]
  },

  setup(props, { slots }) {
    // 缓存和最近使用缓存的 key 队列
    const cache = new Map();
    const keys = new Set();

    // 当前激活的组件实例
    let current = null;

    // 返回虚拟节点的 render 函数
    return () => {
      const vnode = slots.default();
      if (!vnode) return null;

      const name = vnode.type.name || vnode.key;
      if (name && shouldCache(name, props.include, props.exclude)) {
        if (cache.has(vnode.key)) {
          vnode.component = cache.get(vnode.key).component;
          // 更新 key 的使用顺序
          keys.delete(vnode.key);
          keys.add(vnode.key);
        } else {
          cache.set(vnode.key, vnode);
          keys.add(vnode.key);

          // 如果超过缓存数量限制,则移除最早使用的缓存
          if (props.max && keys.size > parseInt(props.max, 10)) {
            const firstKey = keys.values().next().value;
            cache.delete(firstKey);
            keys.delete(firstKey);
          }
        }

        vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE;
      }

      current = vnode;
      return vnode;
    };
  }
};

2. KeepAlive 的核心逻辑

KeepAlive 的源码中,以下几个核心部分需要关注:

a. 缓存机制(cachekeys
  • cache 是一个 Map 对象,用于存储被缓存的组件实例。
  • keys 是一个 Set 对象,记录了缓存组件的 key 顺序,便于管理缓存的顺序。
  • vnode.key 被用作缓存的 key,确保每个实例的唯一性。
b. shouldCache 函数

shouldCache 用于判断当前组件是否符合缓存的条件。它会检查 includeexclude 属性,决定是否要缓存该组件。

function shouldCache(name, include, exclude) {
  if (include && !matches(include, name)) {
    return false;
  }
  if (exclude && matches(exclude, name)) {
    return false;
  }
  return true;
}

function matches(pattern, name) {
  if (Array.isArray(pattern)) {
    return pattern.includes(name);
  } else if (typeof pattern === 'string') {
    return pattern.split(',').includes(name);
  } else if (pattern instanceof RegExp) {
    return pattern.test(name);
  }
  return false;
}
  • include:要缓存的组件列表。
  • exclude:不缓存的组件列表。
c. 缓存的更新和删除

当缓存的数量超过 max 限制时,会移除最早使用的缓存。这是通过 LRU(最近最少使用)策略实现的:

if (props.max && keys.size > parseInt(props.max, 10)) {
  const firstKey = keys.values().next().value;
  cache.delete(firstKey);
  keys.delete(firstKey);
}
  • 每次访问组件时,都会更新 keys 的使用顺序,以保证 keys 最前面的始终是最早使用的组件。
  • 如果 keys.size 超过 max,则会删除最早的 key 和对应的缓存。

3. 生命周期钩子的管理

在 Vue 3 中,KeepAlive 会触发组件的 activateddeactivated 生命周期钩子。以下是相关的核心代码:

  • activated:当缓存组件重新显示时调用。
  • deactivated:当组件被移除但未销毁时调用。
// KeepAlive 组件的生命周期处理
function onActivated(instance) {
  if (instance.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
    queuePostRenderEffect(() => {
      instance.isDeactivated = false;
      if (instance.a) {
        invokeArrayFns(instance.a);
      }
    }, instance.parent);
  }
}

function onDeactivated(instance) {
  if (instance.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
    queuePostRenderEffect(() => {
      instance.isDeactivated = true;
      if (instance.da) {
        invokeArrayFns(instance.da);
      }
    }, instance.parent);
  }
}
  • onActivated:在 KeepAlive 缓存的组件被重新渲染时,会调用该函数,使组件的 isDeactivated 状态为 false,并执行 activated 钩子。
  • onDeactivated:当组件被移除但未销毁时调用 onDeactivated,将 isDeactivated 状态设置为 true,并调用 deactivated 钩子。

4. 总结

<keep-alive> 的核心逻辑包括:

  • 缓存策略:通过 cachekeys 实现 LRU 策略管理。
  • 条件判断:通过 includeexclude 判断是否缓存组件。
  • 生命周期钩子:控制缓存组件的 activateddeactivated 状态。

KeepAlive 组件的实现充分考虑了缓存的性能和灵活性,允许开发者通过配置来控制组件缓存的行为,有效地提升了应用的性能。


http://www.kler.cn/a/380257.html

相关文章:

  • 数学建模学习(135):使用Python基于WSM、WPM、WASPAS的多准则决策分析
  • 【Docker系列】指定系统平台拉取 openjdk:8 镜像
  • EJEAS S2滑雪对讲机全球发布会圆满举办,为滑雪市场注入新活力
  • c++ 贪心算法
  • 证书下行,这些高质量IT证书仍值得考
  • 使用opencv调用TV_L1算法提取光流
  • C++ | Leetcode C++题解之第537题复数乘法
  • 麦麦Docker笔记(一)
  • masm汇编字符输入输出演示
  • 数字身份发展趋势前瞻:去中心化身份
  • OpenCV图像预处理1
  • RuleAlign 规则对齐框架:将医生的诊断规则形式化并注入模型,无需额外人工标注的自动对齐方法
  • Vue Composition API 有哪些常用的 API?
  • CentOS 磁盘扩容
  • 浅谈串口服务器的作用
  • 非线性数据结构之图
  • ICT网络赛道安全考点知识总结5
  • 低代码架构浅析
  • 第七篇: BigQuery中的复杂SQL查询
  • fpga 常量无法改变
  • mybatis源码解析-sql执行流程
  • @Excel若依导出异常/解决BusinessBaseEntity里面的字段不支持导出
  • 数据结构与算法——Java实现 52.力扣98题——验证二叉搜索树
  • MySQL45讲 第十四讲 count(*)这么慢,我该怎么办?
  • 细腻的链接:C++ list 之美的解读
  • 【机器学习】音乐与AI的交响:机器学习在音乐产业中的应用