阐述如何在 Vue 应用中实现复杂的数据缓存策略，例如 LFU (Least Frequently Used) 或 LRU (Least Recently Used) 缓存。

admin
Mon, 28 Jul 2025 18:19:55 +0000
Vue, least, used, 缓存

嘿，大家好！今天咱们来聊聊 Vue 应用里那些让人头大的数据缓存策略，尤其是 LFU 和 LRU 这俩家伙。别怕，咱们用人话把它们给扒个精光，再用代码把它们给驯服。 开场白：缓存，是啥玩意儿？ 想象一下，你是个餐厅服务员。客人点了道菜，你得跑厨房去现做。如果连续三个客人都点了同一道菜，你是不是想把这道菜提前做好，省得来回跑？ 缓存，就是干这事的！ 在 Vue 应用里，我们经常要从服务器获取数据。每次都请求服务器，费时费力还浪费流量。所以，我们可以把数据缓存起来，下次再需要的时候直接从缓存里拿，速度嗖嗖的！ 正餐一：LRU (Least Recently Used) – 最近最少使用 LRU 的核心思想是：如果一个数据最近被访问过，那么它在将来被访问的可能性也很大。所以，我们要优先保留最近被访问的数据，把最久没用的数据给踢出去。 LRU 缓存的实现思路： 数据结构选择： 我们需要一种既能存储键值对，又能记录访问顺序的数据结构。 JavaScript 里没有现成的，所以我们要自己造一个轮子。可以用 Map 或者 链表+对象 来实现。 Map自带顺序，操作更简单，这里我们选择Map。 缓存容 …

继续阅读“阐述如何在 Vue 应用中实现复杂的数据缓存策略，例如 LFU (Least Frequently Used) 或 LRU (Least Recently Used) 缓存。”

The post 阐述如何在 Vue 应用中实现复杂的数据缓存策略，例如 LFU (Least Frequently Used) 或 LRU (Least Recently Used) 缓存。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

嘿，大家好！今天咱们来聊聊 Vue 应用里那些让人头大的数据缓存策略，尤其是 LFU 和 LRU 这俩家伙。别怕，咱们用人话把它们给扒个精光，再用代码把它们给驯服。

开场白：缓存，是啥玩意儿？

想象一下，你是个餐厅服务员。客人点了道菜，你得跑厨房去现做。如果连续三个客人都点了同一道菜，你是不是想把这道菜提前做好，省得来回跑？ 缓存，就是干这事的！

在 Vue 应用里，我们经常要从服务器获取数据。每次都请求服务器，费时费力还浪费流量。所以，我们可以把数据缓存起来，下次再需要的时候直接从缓存里拿，速度嗖嗖的！

正餐一：LRU (Least Recently Used) – 最近最少使用

LRU 的核心思想是：如果一个数据最近被访问过，那么它在将来被访问的可能性也很大。所以，我们要优先保留最近被访问的数据，把最久没用的数据给踢出去。

LRU 缓存的实现思路：

1. 数据结构选择： 我们需要一种既能存储键值对，又能记录访问顺序的数据结构。 JavaScript 里没有现成的，所以我们要自己造一个轮子。可以用 Map 或者 链表+对象 来实现。 Map自带顺序，操作更简单，这里我们选择Map。

2. 缓存容量： 我们需要设定一个缓存的最大容量，超过这个容量就要开始淘汰数据。

3. 访问记录： 每次访问一个数据，都要更新它的访问记录，让它变成“最新”的。

4. 淘汰策略： 当缓存满了，我们要找到“最老”的数据，把它从缓存里移除。

LRU 缓存的代码实现 (基于 Vue 组件)：





Set Cache
Get Cache
Cache Result: {{ cacheResult }}
Cache State: {{ cacheState }}




export default {
  data() {
    return {
      key: '',
      value: '',
      cacheResult: '',
      cache: new Map(),
      capacity: 5,
      cacheState: ''
    };
  },
  methods: {
    setCache() {
      if (this.key && this.value) {
        this.set(this.key, this.value);
        this.cacheState = 'Set ' + this.key + ': ' + this.value;
      }
    },
    getCache() {
      if (this.key) {
        const result = this.get(this.key);
        this.cacheResult = result !== undefined ? result : 'Not found';
        this.cacheState = 'Get ' + this.key;

      }
    },
    get(key) {
      if (!this.cache.has(key)) {
        return undefined;
      }
      const value = this.cache.get(key);
      this.cache.delete(key); // Move to the end (most recently used)
      this.cache.set(key, value);
      return value;
    },
    set(key, value) {
      if (this.cache.has(key)) {
        this.cache.delete(key);
      }
      this.cache.set(key, value);
      if (this.cache.size > this.capacity) {
        // Remove the least recently used element
        const firstKey = this.cache.keys().next().value;
        this.cache.delete(firstKey);
      }
    }
  }
};


代码解释：

cache: 一个 Map 对象，用来存储缓存数据。Key 是缓存的键，Value 是缓存的值。

capacity: 缓存的最大容量。

get(key): 从缓存中获取数据。如果找到了，就把这个数据移到 Map 的末尾，表示它最近被访问过。

set(key, value): 把数据存入缓存。如果缓存满了，就删除 Map 的第一个元素，也就是最久没用的数据。

LRU 的优点和缺点：

优点： 实现简单，效果不错，能有效提高缓存命中率。

缺点： 对所有数据的处理方式都一样，不考虑数据的访问频率。 比如，一个数据虽然很久没用，但它很重要，经常被访问，LRU 也会把它踢出去。

正餐二：LFU (Least Frequently Used) – 最不经常使用

LFU 的核心思想是：如果一个数据被访问的频率很低，那么它在将来被访问的可能性也很低。所以，我们要优先保留访问频率高的数据，把访问频率最低的数据给踢出去。

LFU 缓存的实现思路：

1. 数据结构选择： 我们需要两个数据结构：

一个 Map 用来存储键值对。

另一个 Map 用来记录每个键的访问频率。

2. 缓存容量： 和 LRU 一样，我们需要设定一个缓存的最大容量。

3. 访问记录： 每次访问一个数据，都要更新它的访问频率。

4. 淘汰策略： 当缓存满了，我们要找到访问频率最低的数据，把它从缓存里移除。

LFU 缓存的代码实现 (基于 Vue 组件)：





Set Cache
Get Cache
Cache Result: {{ cacheResult }}
Cache State: {{ cacheState }}




export default {
  data() {
    return {
      key: '',
      value: '',
      cacheResult: '',
      cache: new Map(),
      frequencies: new Map(),
      capacity: 5,
      minFrequency: 0,
      cacheState: ''
    };
  },
  methods: {
    setCache() {
      if (this.key && this.value) {
        this.set(this.key, this.value);
        this.cacheState = 'Set ' + this.key + ': ' + this.value;
      }
    },
    getCache() {
      if (this.key) {
        const result = this.get(this.key);
        this.cacheResult = result !== undefined ? result : 'Not found';
        this.cacheState = 'Get ' + this.key;
      }
    },
    get(key) {
      if (!this.cache.has(key)) {
        return undefined;
      }
      const frequency = this.frequencies.get(key) || 0;
      this.frequencies.set(key, frequency + 1);
      this.minFrequency = Math.min(this.minFrequency, frequency + 1);
      return this.cache.get(key);
    },
    set(key, value) {
      if (this.cache.has(key)) {
        this.cache.set(key, value);
        this.frequencies.set(key, this.frequencies.get(key) + 1);
        return;
      }

      if (this.cache.size >= this.capacity) {
        this.evict();
      }

      this.cache.set(key, value);
      this.frequencies.set(key, 1);
      this.minFrequency = 1;
    },
    evict() {
      let keyToRemove = null;
      let minFreq = Infinity;

      this.frequencies.forEach((freq, key) => {
        if (freq < minFreq) {
          minFreq = freq;
          keyToRemove = key;
        }
      });

      if (keyToRemove) {
        this.cache.delete(keyToRemove);
        this.frequencies.delete(keyToRemove);
        this.minFrequency = minFreq;
      }
    }
  }
};


代码解释：

cache: 一个 Map 对象，用来存储缓存数据。Key 是缓存的键，Value 是缓存的值。

frequencies: 另一个 Map 对象，用来记录每个键的访问频率。Key 是缓存的键，Value 是访问频率。

capacity: 缓存的最大容量。

minFrequency: 记录当前缓存中最小的访问频率。

get(key): 从缓存中获取数据。如果找到了，就把这个数据的访问频率加 1。

set(key, value): 把数据存入缓存。如果缓存满了，就找到访问频率最低的数据，把它从缓存里移除。

evict(): 负责移除缓存中访问频率最低的数据。

LFU 的优点和缺点：

优点： 能更准确地反映数据的访问模式，避免重要数据被错误地淘汰。

缺点： 实现复杂，需要维护额外的数据结构。 如果数据在一段时间内访问频率很高，之后就很少访问了，LFU 可能会一直保留这个数据，即使它已经没用了。

总结：LRU vs LFU

特性 | LRU (最近最少使用) | LFU (最不经常使用)
核心思想 | 最近使用的数据更可能在将来被使用 | 访问频率高的数据更可能在将来被使用
实现难度 | 简单 | 较复杂
空间复杂度 | 较低 | 较高
适用场景 | 数据访问模式比较均匀，最近访问的数据通常也比较重要 | 数据访问频率差异较大，需要区分重要数据的场景
优点 | 实现简单，性能好 | 能更准确地反映数据的访问模式，避免重要数据被错误地淘汰
缺点 | 不考虑数据的访问频率，可能错误地淘汰重要数据 | 实现复杂，需要维护额外的数据结构，对历史数据敏感，容易出现“缓存污染”

额外佐料： Vue 中使用缓存的一些技巧

1. keep-alive 组件： Vue 提供的内置组件，可以缓存组件的状态，避免重复渲染。 适用于需要频繁切换，但不需要每次都重新渲染的组件。

<keep-alive>
  <component :is="currentComponent"></component>
</keep-alive>

2. 计算属性和 watch： 利用计算属性的缓存特性，或者使用 watch 监听数据的变化，手动更新缓存。

computed: {
  cachedData() {
    // 从缓存中获取数据，如果不存在，就从服务器获取
    if (this.cache[this.dataKey]) {
      return this.cache[this.dataKey];
    } else {
      this.fetchData();
      return this.data; // 假设 fetchData 会更新 this.data
    }
  }
},
watch: {
  data(newValue) {
    // 数据发生变化，更新缓存
    this.cache[this.dataKey] = newValue;
  }
}

3. Vuex： 使用 Vuex 集中管理状态，可以方便地实现全局缓存。

4. LocalStorage / SessionStorage： 利用浏览器的本地存储功能，可以持久化缓存数据。 适用于不经常变化的数据，例如用户信息、配置信息等。 注意：LocalStorage 的容量有限，不适合存储大量数据。

5. IndexedDB： 更强大的浏览器数据库，可以存储大量结构化数据。 适用于需要存储大量复杂数据的场景。

总结：缓存策略的选择，没有银弹

选择哪种缓存策略，取决于你的具体应用场景和需求。

如果你的数据访问模式比较均匀，LRU 是一个不错的选择。

如果你的数据访问频率差异很大，LFU 可能会更适合你。

如果你的数据量很小，或者对实时性要求很高，可以考虑不使用缓存。

记住，缓存不是万能的，过度使用缓存可能会导致数据不一致，增加维护成本。 所以，在选择缓存策略的时候，一定要权衡利弊，选择最适合你的方案。

好了，今天的讲座就到这里。希望大家对 Vue 应用中的缓存策略有了更深入的了解。 记住，代码只是工具，理解背后的思想才是最重要的。 下次再见！