vue keep-alive 原理

在Vue中,keep-alive是一个抽象组件,用于缓存不活动的组件实例,以避免重复渲染和销毁,从而提高性能。下面详细解释其原理:

1. 基本概念-

作用:包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

特性 :- 当组件在<keep-alive>内切换时,它的activateddeactivated两个生命周期钩子会被执行。- 组件不会被销毁,也不会重新创建,而是被缓存起来。

2. 实现原理

(1) 缓存机制

keep-alive内部维护了一个缓存对象cache)和一个键数组keys)。 每个被缓存的组件都有一个唯一的key(默认为组件的name选项或组件的tag+组件的key属性)。- 当组件被切换出去时,keep-alive会将组件实例存入cache对象中,同时将key推入keys数组。 当再次切换到相同组件时,直接从缓存中取出实例并挂载。

(2) LRU缓存策略(Least Recently Used)

如果设置了max属性(最大缓存数),当缓存组件数量超过max时,keep-alive会移除最久未被使用的缓存(数组keys的第一个元素)。每次访问缓存组件时,都会将对应的key移到数组末尾,确保最近使用的在最后。

(3) 组件渲染

keep-alive自身不会渲染DOM元素,它通过render函数返回其包裹的子组件。 在render函数中:首先获取第一个子组件(注意:只能包裹一个子组件)。 根据子组件的keycache中查找。 如果命中缓存,则直接返回缓存的组件实例(vnode.componentInstance)。如果没有命中,则将其加入缓存(同时检查max限制)。 同时记录子组件的data.keepAlivetrue(用于后续生命周期触发)

。### 3. 生命周期钩子

activated : 当缓存的组件被激活(展示)时调用。 内部会调用vnode.componentInstance.$emit('activated'),触发组件的activated钩子。

deactivated :当缓存的组件被停用(隐藏)时调用。 内部会调用vnode.componentInstance.$emit('deactivated'),触发组件的deactivated钩子。

4. 源码关键逻辑(简化版)

js 复制代码
// 简化后的render函数render()
{const slot = this.$slots.defaultconst vnode = getFirstComponentChild(slot) 
// 获取第一个子组件
const key = vnode.key ?? vnode.componentOptions.Ctor.cidif (cache[key]) {
// 命中缓存,直接返回缓存的实例
vnode.componentInstance = cache[key].componentInstance
// 调整key位置(LRU)
remove(keys, key)keys.push(key)
} else {
// 未命中则加入缓存
cache[key] = vnodekeys.push(key)
// 如果超出max,删除第一个(最久未使用)
if (this.max && keys.length > this.max) {
pruneCacheEntry(cache, keys[0], keys)
}
}
vnode.data.keepAlive = true 
// 标记为keep-alive组件return vnode}

5. 使用示例

vue 复制代码
<template>
    <keep-alive :max="10">
        <component :is="currentComponent"></component>
    </keep-alive>
</template>

6. 注意事项

include/exclude : 通过include(包含)和exclude(排除)属性控制哪些组件被缓存(使用组件name)。

动态组件 :- 常用于动态组件(<component :is="...">)和路由视图(<router-view>)。

缓存策略 :默认缓存所有符合条件的组件,但可通过include精确控制。避免缓存过多导致内存占用过高,合理设置max

7. 与Vue 3的区别

在Vue 3中,keep-alive的实现原理类似,但有以下变化:

使用setup和组合式API。

生命周期钩子名称改为onActivatedonDeactivated(需在setup中使用)。

缓存数据结构与Vue 2略有不同。

总结

keep-alive通过维护一个缓存对象和LRU策略,实现了组件的缓存和复用,避免了重复渲染带来的性能开销,同时提供了激活/停用钩子函数以便开发者控制缓存组件的状态。

相关推荐
一 乐3 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
科技D人生3 小时前
Vue.js 学习总结(20)—— Vue-Office 实战:word、pdf、excel、ppt 多种文档的在线预览
vue.js·word·vue-pdf·stylesheet·docx-preview·vue-office
vx1_Biye_Design3 小时前
基于Spring Boot+Vue的学生管理系统设计与实现-计算机毕业设计源码46223
java·vue.js·spring boot·spring·eclipse·tomcat·maven
vx_Biye_Design3 小时前
基于Spring Boot+vue的湖北旅游景点门票预约平台的设计--毕设附源码29593
java·vue.js·spring boot·spring cloud·servlet·eclipse·课程设计
hedley(●'◡'●)3 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_8115175153 小时前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
百思可瑞教育3 小时前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育
百锦再3 小时前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
hdsoft_huge3 小时前
1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】
vue.js·spring boot·后端
CappuccinoRose4 小时前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明