一次keepAlive缓存失效的经历

401 阅读3分钟

keepAlive缓存的问题

在路由中加上了keepAlive: true 进行路由缓存。

{
  path: '/list',
  name: 'list',
  component: () => import('./views/keep-alive/list.vue'),
    meta: {
      keepAlive: true //需要被缓存
    }
},
​

我给需要的路由加上缓存之后神奇的是并没有生效,我录入输入,然后跳转去了其他页面,然后切换回来这个页面,我刚刚输入的值被清空了。很显然加上了keepalive并没有生效。那是什么原因呢?

经过一顿排查发现是项目进行路由改造的时候,将vue页面的名字改成了特定的编码,在改造页面名字的时候我就删除的vue页面的name,导致页面没有缓存,这个keepalive没有生效的罪魁祸首就是我将页面的name删了,加上页面的name之后就ok了。需要注意的是vue页面的name不要重复,如果重复也会定位不上去。

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。一旦使用keep-alive包裹组件,此时mouted,created等钩子函数只会在第一次进入组件时调用,当再次切换回来时将不会调用。此时如果我们还想在每次切换时做一些事情,就需要用到另外的周期函数,actived和deactived,这两个钩子函数只有被keepalive包裹后才会调用。
​
​
<keep-alive :include="whiteList" :exclude="blackList" :max="amount">
     <component :is="currentComponent"></component>
</keep-alive>
​
include定义缓存白名单,keep-alive会缓存命中的组件;exclude定义缓存黑名单,被命中的组件将不会被缓存;max定义缓存组件上限,超出上限使用`LRU`的策略置换缓存数据。

keep-alive 原理

keep-alive中运用了LRU(Least Recently Used)算法

1.获取 keep-alive 包裹着的第一个子组件对象及其组件名; 如果 keep-alive 存在多个子元素,keep-alive 要求同时只有一个子元素被渲染。所以在开头会获取插槽内的子元素,调用 getFirstComponentChild 获取到第一个子元素的 VNode

2.根据设定的黑白名单(如果有)进行条件匹配,决定是否缓存。不匹配,直接返回组件实例(VNode),否则开启缓存策略。

3.根据组件ID和tag生成缓存Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值并更新该key在this.keys中的位置(更新key的位置是实现LRU置换策略的关键)。

如果不存在,则在this.cache对象中存储该组件实例并保存key值,之后检查缓存的实例数量是否超过max设置值,超过则根据LRU置换策略删除最近最久未使用的实例(即是下标为0的那个key)。最后将该组件实例的keepAlive属性值设置为true

LRU (least-recently-used)- 最近最少使用策略 以时间作为参考,如果数据最近被访问过,那么将来被访问的几率会更高,如果以一个数组去记录数据,当有一数据被访问时,该数据会被移动到数组的头部,表明最近被使用过,当缓存溢出时,会删除数组的末尾数据,即将最不频繁使用的数据移除。(keep-alive 的优化处理)

\