Vue KeepAlive[转]

Vue


原文引自 (opens new window)

# 缓存优化 - LRU

程序的内存空间是有限的,所以我们无法无节制的对数据进行存储,这时候需要有策略去淘汰不那么重要的数据,保持最大数据存储量的一致。这种类型的策略称为缓存优化策略,根据淘汰的机制不同,常用的有以下三类。

  1. FIFO: 先进先出策略,我们通过记录数据使用的时间,当缓存大小即将溢出时,优先清除离当前时间最远的数据。

  2. LRU: 最近最少使用。LRU 策略遵循的原则是,如果数据最近被访问(使用)过,那么将来被访问的几率会更高,如果以一个数组去记录数据,当有一数据被访问时,该数据会被移动到数组的末尾,表明最近被使用过,当缓存溢出时,会删除数组的头部数据,即将最不频繁使用的数据移除。

  3. LFU: 计数最少策略。用次数去标记数据使用频率,次数最少的会在缓存溢出时被淘汰。

这三种缓存算法各有优劣,各自适用不同场景,而我们看 keep-alive 在缓存时的优化处理,很明显利用了 LRU 的缓存策略。我们看关键的代码

var keepAlive = {
  render: function() {
    ···
    if (cache[key]) {
      vnode.componentInstance = cache[key].componentInstance;
      remove(keys, key);
      keys.push(key);
    } else {
      cache[key] = vnode;
      keys.push(key);
      if (this.max && keys.length > parseInt(this.max)) {
        pruneCacheEntry(cache, keys[0], keys, this._vnode);
      }
    }
  }
}
function remove (arr, item) {
  if (arr.length) {
    var index = arr.indexOf(item);
    if (index > -1) {
      return arr.splice(index, 1)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 例子

结合一个实际的例子分析缓存逻辑的实现。

  1. 有三个组件 child1,child2,child3,keep-alive 的最大缓存个数设置为 2

  2. 用 cache 对象去存储组件 vnode,key 为组件名字,value 为组件 vnode 对象,用 keys 数组去记录组件名字,由于是数组,所以 keys 为有序。

  3. child1,child2 组件依次访问,缓存结果为

keys = ['child1', 'child2']
cache = {
  child1: child1Vnode,
  child2: child2Vnode,
}
1
2
3
4
5
  1. 再次访问到 child1 组件,由于命中了缓存,会调用 remove 方法把 keys 中的 child1 删除,并通过数组的 push 方法将 child1 推到尾部。缓存结果修改为
keys = ['child2', 'child1']
cache = {
  child1: child1Vnode,
  child2: child2Vnode,
}
1
2
3
4
5
  1. 访问到 child3 时,由于缓存个数限制,初次缓存会执行 pruneCacheEntry 方法对最少访问到的数据进行删除。pruneCacheEntry 的定义如下
function pruneCacheEntry (cache,key,keys,current) {
    var cached###1 = cache[key];
    // 销毁实例
    if (cached###1 && (!current || cached###1.tag !== current.tag)) {
      cached###1.componentInstance.$destroy();
    }
    cache[key] = null;
    remove(keys, key);
  }
1
2
3
4
5
6
7
8
9

删除缓存时会把 keys[0]代表的组件删除,由于之前的处理,最近被访问到的元素会位于数组的尾部,所以头部的数据往往是最少访问的,因此会优先删除头部的元素。并且会再次调用 remove 方法,将 keys 的首个元素删除。

这就是 vue 中对 keep-alive 缓存处理的优化过程。

Last Updated: 10/21/2024, 4:15:17 PM