Vue keep-alive源码解析

239 阅读3分钟

在性能优化上,最常见的就是缓存。对需要经常访问的资源进行缓存,减少请求或者是初始化的过程,从而降低时间或内存的消耗。Vue 为我们提供了缓存组件 keep-alive,它可用于路由级别或组件级别的缓存。

但其中的缓存原理你是否了解,组件缓存渲染又是如何工作。那么本文就来解析 keep-alive 的源码。

首先我们用到了# LRU策略

在使用 keep-alive 时,可以添加 prop 属性 includeexcludemax 允许组件有条件的缓存。既然有限制条件,旧的组件需要删除缓存,新的组件就需要加入到最新缓存, LRU(Least recently used,最近最少使用)策略根据数据的历史访问记录来进行淘汰数据。LRU 策略的设计原则是,如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

image.png

  • 现在缓存最大只允许存3个组件,ABC三个组件依次进入缓存,没有任何问题

  • 当D组件被访问时,内存空间不足,A是最早进入也是最旧的组件,所以A组件从缓存中删除,D组件加入到最新的位置

  • 当B组件被再次访问时,由于B还在缓存中,B移动到最新的位置,其他组件相应的往后一位

  • 当E组件被访问时,内存空间不足,C变成最久未使用的组件,C组件从缓存中删除,E组件加入到最新的位置

组件实现原理

QQ截图20220830141437.png kepp-alive 实际是一个抽象组件,只对包裹的子组件做处理,并不会和子组件建立父子关系,也不会作为节点渲染到页面上。在组件开头就设置 abstract 为 true,代表该组件是一个内置组件。

如果 keep-alive 存在多个子元素,keep-alive 要求同时只有一个子元素被渲染。所以在开头会获取插槽内的子元素,调用 getFirstComponentChild 获取到第一个子元素的 VNode

image.png 接着判断当前组件是否符合缓存条件,组件名与include不匹配或与exclude匹配都会直接退出并返回 VNode,不走缓存机制。

image.png 匹配条件通过会进入缓存机制的逻辑,如果命中缓存,从 cache 中获取缓存的实例设置到当前的组件上,并调整 key 的位置将其放到最后。如果没命中缓存,将当前 VNode 缓存起来,并加入当前组件的 key。如果缓存组件的数量超出 max 的值,即缓存空间不足,则调用 pruneCacheEntry 将最旧的组件从缓存中删除,即 keys[0] 的组件。之后将组件的 keepAlive 标记为 true,表示它是被缓存的组件。

image.png pruneCacheEntry 负责将组件从缓存中删除,它会调用组件 $destroy 方法销毁组件实例,缓存组件置空,并移除对应的 key

image.png keep-alive 在 mounted 会监听 include 和 exclude 的变化,属性发生改变时调整缓存和 keys 的顺序,最终调用的也是 pruneCacheEntry

小结cache 用于缓存组件,keys 存储组件的 key,根据LRU策略来调整缓存组件。keep-aliverender 中最后会返回组件的 VNode,因此我们也可以得出一个结论,keep-alive 并非真的不会渲染,而是渲染的对象是包裹的子组件。


作者:出来吧皮卡丘
链接:juejin.cn/post/686220… 来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。