【vue设计与实现】内部组件和模块 2 - 缓存管理

在前面的实现中,使用一个Map对象来实现对组件的缓存:

const cache = new Map()

该Map对象的键也就是vnode.type的值,值是用于描述组件的vnode对象

当前KeepAlive组件缓存的处理逻辑可以总结为:

  1. 如果缓存存在,则继承组件实例,将keptAlive改为true
  2. 如果缓存不存在,则设置缓存

这里的问题在于,当缓存不存在的时候,总是会设置新的缓存。这会导致缓存不断增加,极端情况下会占用大量内存。
为了解决这个问题,必须设置一个缓存阈值,当缓存数量超过指定阈值时对缓存进行修剪

Vue.js当前采用的修剪策略叫“最新一次访问”。
首先要为缓存设置最大容器,也就是通过KeepAlive组件的max属性来设置,例如:

<KeepAlive :max="2">
	<component :is="dynamicComp" />
</KeepAlive>

在上面这段代码中,设置缓存的容量为2,假设有三个组件Comp1,Comp2,Comp3,并且他们都会被缓存。然后,开始模拟组件切换过程中缓存的变化,如下所示:

  1. 初始渲染Comp1并缓存它,此时缓存队列是[Comp1],并且最新一次访问(或渲染)的组件时Comp1
  2. 切换到Comp2并缓存它,此时缓存队列是[Comp1,Comp2],并且最新一次访问(或渲染)的组件时Comp2
  3. 切换到 Comp3,此时缓存容量已满,需要修剪,而当前最新一次访问(或渲染)的组件是Comp2,所以该被修剪的是Comp1,当缓存修剪完毕后,将会出现空余的缓存空间用来存储Comp3,所以,现在的缓存队列是[Comp2,Comp3],并且最新一次渲染的组件变成了Comp3

还可以换一种切换组件的方式,如下所示

  1. 初始渲染Comp1并缓存它,此时缓存队列是[Comp1],并且最新一次访问(或渲染)的组件时Comp1
  2. 切换到Comp2并缓存它,此时缓存队列是[Comp1,Comp2],并且最新一次访问(或渲染)的组件时Comp2
  3. 再次换会Comp1,由于Comp1已经在缓存队列中,所以不需要修剪缓存,只需要激活组件即可,但要将最新一次渲染的组件设置为Comp1
  4. 切换到 Comp3,此时缓存容量已满,需要修剪,由于Comp1是最新一次被渲染的,所以它是“安全”的,即不会被修剪掉,所以最终会被修剪掉的是Comp2。于是,现在的缓存队列是:[Comp1,Comp3],并且最新一次渲染的组件变成了Comp3

可以看到,在不同的模拟策略下,最终的缓存结果会有所不同。
“最新一次访问”的缓存修剪策略的核心在于,需要把当前访问(或渲染)的组件作为最新一次渲染的组件,并且该组件在缓存修剪过程中始终是安全的,即不会被修剪

而且在用户接口层面,允许用户实现自定义的缓存策略,这体现在KeepAlive组件新增了cache接口,允许用户执行缓存实例:

<KeepAlive :cache="cache">
	<Comp />
</KeepAlive>

缓存示例需要满足固定的格式,一个基本的缓存示例的实现如下:

// 自定义实现
const _cache = new Map()
const cache: KeepAliveCache = {
	get(key){
		_cache.get(key)
	},
	set(key,value){
		_cache.set(key,value)
	},
	delete(key){
		_cache.delete(key)
	},
	forEach(fn){
		_cache.forEach(fn)
	}
}

在KeepAlive组件的内部实现中,如果用户提供了自定义的缓存实例,则直接使用该缓存实例来管理缓存。从本质上来说,这等价于将缓存的管理权限从KeepAlive组件转交给用户了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值