vue中keep-alive的实现以及LRU缓存策略

292 阅读2分钟

vue中keep-alive的实现以及LRU缓存策略

基本思路

  1. keep-alive要求只有一个子元素被渲染,所以一般搭配动态组件component或router-view使用。

因为我们是在keep-alive中开发,所以可以先获取默认插槽,然后获取他的第一个子元素和他的组件名,根据设置的include/exclude进行匹配,如果匹配到会走缓存,没有的话会直接返回组件实例。

  1. 命中缓存直接获取,同时更新key的位置

根据组件id和tag生成缓存key,并在缓存数组中查找此组件是否已经被缓存,如果命中,直接取出,同时更新key在缓存数组中的位置(更新位置是LRU缓存策略实现的关键)

  1. 如果没有命中就加入缓存,同时检查缓存的实例是否超过max

将组件实例加入cache数组,并存储key值,然后检查key数组的长度是否已经超过了最大值。如果超过了则会处理掉最久不用的实例

  1. 设置组件实例中data内的keepAlive标志位

abstract

与transition相似,keep-alive也是一个抽象组件,它本身不会渲染一个DOM元素,也不会出现在组件的父组件链中

组件一旦被缓存,重新渲染时的created,mounted等生命周期就不会执行,而是提供了activated和deactivated两个钩子

vue在初始化生命周期的时候,为组件实例建立父子关系的时候会根据abstract属性判断是否需要渲染某个组件,keep-alive中设置了abstract:true 所以渲染时会跳过这个组件实例

export function initLifecycle (vm: Component) {
	const options = vm.$options
  	// locate first non-abstract parent
  	let parent = options.parent
  	if (parent && !options.abstract) {
    	while (parent.$options.abstract && parent.$parent) {
      		parent = parent.$parent
   	}
   	parent.$children.push(vm)
 	
}

keep-alive的首次渲染和缓存渲染

首次渲染的时候,除了在<keep-alive>中建立缓存,设置vnode.data.keepAlive为true,其他过程和普通组件是一致的。

缓存渲染的时候,会根据vnode.componentInstance(首次渲染时为undefined)和vnode.data.keepAlive判断不再执行组件的created和mounted,直接对缓存的组件patch,最后直接把DOM插入到目标元素中,完成更新。

LRU(last recently used)缓存策略

核心思想为

如果数据最近被访问过,那以后访问这条数据的可能性就越高

最常见的实现是使用一个链表保存缓存数据,详细的实现如下:

  1. 新数据插入到链表头部
  2. 缓存命中时,将数据移动到链表头部
  3. 当链表达到最大值时,删除尾部数据

最后附上一道leetcode关于lru的题目

leetcode-cn.com/problems/lr…