引入:SPA单页面应用
在使用框架开发单页面应用(如Vue)时,性能优化是开发过程中的一个重要环节。组件缓存是性能优化的一个关键点之一。今天我们将深入探讨如何通过使用
**keep-alive**
来实现组件的缓存以及其背后的工作原理。
keep-alive的介绍
**keep-alive**
是 Vue 中的一个内置组件,用于缓存动态组件或路由组件,以提升应用性能。使用**keep-alive**
可以避免频繁销毁和重建组件,从而减少不必要的性能开销。
基本用法
<template>
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</template>
<script>
export default {
data() {
return {
currentComponent: 'MyComponent'
}
}
}
</script>
在这段代码中,’ keep-alive ’ 包裹了一个动态组件,即使 '** currentComponent** ’ 组件发生变化,之前加载过的组件状态也会被保留。
此外,**keep-alive**
** 确实可以通过路由的 **meta**
字段来实现组件的缓存控制。 **
在 Vue Router 中,可以在路由配置中为每个路由设置一个
**meta**
字段,然后在**keep-alive**
组件的 include 或 exclude 属性中使用这个meta
字段的值来动态控制缓存。 这种方式可以让我们通过路由的meta
字段灵活控制哪些组件需要被缓存,而不用手动管理 include 或 exclude 属性的值。
const routes = [
{
path: '/componentA',
component: ComponentA,
<!--keepAlive:在路由配置中为需要缓存的路由设置的字段。true 表示需要缓存,false 或不设置表示不缓存。 -->
meta: { keepAlive: true }
},
{
path: '/componentB',
component: ComponentB,
meta: { keepAlive: false }
},
// 其他路由配置
];
然后,在
**keep-alive**
组件中,我们可以通过一个计算属性或方法来动态地决定哪些组件应该被缓存:
<template>
<keep-alive :include="cachedComponents">
<router-view></router-view>
</keep-alive>
</template>
<script>
export default {
computed: {
// cachedComponents:通过计算属性获取需要缓存的组件名称列表,并传递给 keep-alive 的 include 属性。
cachedComponents() {
// $route.matched:返回当前匹配到的所有路由记录。
return this.$route.matched
.filter(route => route.meta.keepAlive)
.map(route => route.name);
}
}
}
</script>
基本属性
- include/exclude: 用于指定哪些组件需要被缓存或不被缓存。 其中:exclude的优先级大于include
<!--include代表匹配到的组件被缓存 -->
<keep-alive include="MyComponent">
<component :is="currentComponent"></component>
</keep-alive>
<!--exclude代表怕匹配到的组件不被缓存 -->
<keep-alive include="MyComponent">
<component :is="currentComponent"></component>
</keep-alive>
当
**keep-alive**
同时存在 **include **和 **exclude ** 属性时,exclude 的优先级更高。也就是说,如果一个组件既在 exclude ** 中,又在 exclude ** 中,那么这个组件将不会被缓存。
<keep-alive include="ComponentA,ComponentB" exclude="ComponentC">
<router-view></router-view>
</keep-alive>
在这个例子中,
ComponentA
和ComponentB
会被缓存,但即使ComponentC
被包含在include
中,由于exclude
的优先级更高,ComponentC
仍然不会被缓存。
- max : 设置缓存的组件数量上限,超过这个数量时,最久未使用的组件实例将被销毁。
<!-- 在这里最多缓存10个组件,超出部分会被销毁 -->
<keep-alive :max="10">
<component :is="currentComponent"></component>
</keep-alive>
生命周期钩子
**keep-alive**
缓存的组件会触发两个额外的生命周期钩子:
- activated: 当组件从缓存中被激活时调用。
- deactivated: 当组件被缓存时调用,而不是被销毁。
原理概述
**keep-alive**
组件本质上是一个高阶组件,通过内部管理一个缓存对象来存储组件实例。当组件被缓存时,它的 DOM 会被移除,但实例和数据状态会被保留。当再次激活该组件时,它的实例会从缓存中恢复,而不需要重新创建。- 超过组件缓存的数量上限时,会涉及到一个LRU算法,用来计算最久没有使用过的组件,并进行销毁。这里以力扣的LRU算法题来展示此原理。146LRU缓存
/**
* @param {number} capacity
*/
var LRUCache = function(capacity) {
// 存储到原型里面,利用map
this.limit = capacity
this.cache = new Map()
};
/**
* @param {number} key
* @return {number}
*/
// 原型
// 每次获取的时候,先获取,然后再删除,在添加,这样能保证他在后面添加了,是已经使用过的,使用次数
LRUCache.prototype.get = function(key) {
let temp
if (this.cache.has(key)) {
temp = this.cache.get(key)
console.log(temp)
this.cache.delete(key)
this.cache.set(key, temp)
}
return temp ?? -1
};
/**
* @param {number} key
* @param {number} value
* @return {void}
*/
LRUCache.prototype.put = function(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key)
}
this.cache.set(key, value)
// 超过限额添加的时候,提取map元素的第一个然后删除
if (this.cache.size > this.limit) {
this.cache.delete(this.cache.keys().next().value)
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/
总结
在现代的前端开发中,单页面应用(SPA)的性能优化是开发过程中至关重要的一环。其中,组件缓存是提高应用性能的一个关键策略。通过缓存已加载的组件,可以避免不必要的资源消耗和重复渲染,从而提升用户体验。完结啦!撒花~~