当前位置: 首页 > news >正文

在vue中对keep-alive的理解,它是如何实现的,具体缓存的是什么?

对keep-alive的理解,它是如何实现的,具体缓存的是什么?

  • (1)keep-alive有以下三个属性:
    • 注意:keep-alive 包裹动态组件时,会缓存不活动的组件实例。
    • 主要流程
  • (2)keep-alive 的实现
    • render函数
  • (3)keep-alive 本身的创建过程和 patch 过程
  • (4)LRU (least recently used)缓存策略

如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。

(1)keep-alive有以下三个属性:

include 字符串或正则表达式,只有名称匹配的组件会被匹配;
exclude 字符串或正则表达式,任何名称匹配的组件都不会被缓存;
max 数字,最多可以缓存多少组件实例。

注意:keep-alive 包裹动态组件时,会缓存不活动的组件实例。

主要流程

判断组件 name ,不在 include 或者在 exclude 中,直接返回 vnode,说明该组件不被缓存。
获取组件实例 key ,如果有获取实例的 key,否则重新生成。
key生成规则,cid +“∶∶”+ tag ,仅靠cid是不够的,因为相同的构造函数可以注册为不同的本地组件。
如果缓存对象内存在,则直接从缓存对象中获取组件实例给 vnode ,不存在则添加到缓存对象中。 5.最大缓存数量,当缓存组件数量超过 max 值时,清除 keys 数组内第一个组件。

(2)keep-alive 的实现

const patternTypes: Array<Function> = [String, RegExp, Array] // 接收:字符串,正则,数组export default {name: 'keep-alive',abstract: true, // 抽象组件,是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。props: {include: patternTypes, // 匹配的组件,缓存exclude: patternTypes, // 不去匹配的组件,不缓存max: [String, Number], // 缓存组件的最大实例数量, 由于缓存的是组件实例(vnode),数量过多的时候,会占用过多的内存,可以用max指定上限},created() {// 用于初始化缓存虚拟DOM数组和vnode的keythis.cache = Object.create(null)this.keys = []},destroyed() {// 销毁缓存cache的组件实例for (const key in this.cache) {pruneCacheEntry(this.cache, key, this.keys)}},mounted() {// prune 削减精简[v.]// 去监控include和exclude的改变,根据最新的include和exclude的内容,来实时削减缓存的组件的内容this.$watch('include', (val) => {pruneCache(this, (name) => matches(val, name))})this.$watch('exclude', (val) => {pruneCache(this, (name) => !matches(val, name))})},
}

render函数

1.会在 keep-alive 组件内部去写自己的内容,所以可以去获取默认 slot 的内容,然后根据这个去获取组件
2.keep-alive 只对第一个组件有效,所以获取第一个子组件。
3.和 keep-alive 搭配使用的一般有:动态组件 和router-view

render () {//function getFirstComponentChild (children: ?Array<VNode>): ?VNode {if (Array.isArray(children)) {for (let i = 0; i < children.length; i++) {const c = children[i]if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {return c}}}}const slot = this.$slots.default // 获取默认插槽const vnode: VNode = getFirstComponentChild(slot)// 获取第一个子组件const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions // 组件参数if (componentOptions) { // 是否有组件参数// check patternconst name: ?string = getComponentName(componentOptions) // 获取组件名const { include, exclude } = thisif (// not included(include && (!name || !matches(include, name))) ||// excluded(exclude && name && matches(exclude, name))) {// 如果不匹配当前组件的名字和include以及exclude// 那么直接返回组件的实例return vnode}const { cache, keys } = this// 获取这个组件的keyconst key: ?string = vnode.key == null// same constructor may get registered as different local components// so cid alone is not enough (#3269)? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : ''): vnode.keyif (cache[key]) {// LRU缓存策略执行vnode.componentInstance = cache[key].componentInstance // 组件初次渲染的时候componentInstance为undefined// make current key freshestremove(keys, key)keys.push(key)// 根据LRU缓存策略执行,将key从原来的位置移除,然后将这个key值放到最后面} else {// 在缓存列表里面没有的话,则加入,同时判断当前加入之后,是否超过了max所设定的范围,如果是,则去除// 使用时间间隔最长的一个cache[key] = vnodekeys.push(key)// prune oldest entryif (this.max && keys.length > parseInt(this.max)) {pruneCacheEntry(cache, keys[0], keys, this._vnode)}}// 将组件的keepAlive属性设置为truevnode.data.keepAlive = true // 作用:判断是否要执行组件的created、mounted生命周期函数}return vnode || (slot && slot[0])
}

keep-alive 具体是通过 cache 数组缓存所有组件的 vnode 实例。当 cache 内原有组件被使用时会将该组件 key 从 keys 数组中删除,然后 push 到 keys数组最后,以便清除最不常用组件。
实现步骤:
1.获取 keep-alive 下第一个子组件的实例对象,通过他去获取这个组件的组件名
2.通过当前组件名去匹配原来 include 和 exclude,判断当前组件是否需要缓存,不3.需要缓存,直接返回当前组件的实例vNode需要缓存,判断他当前是否在缓存数组里面:
(1)存在,则将他原来位置上的 key 给移除,同时将这个组件的 key 放到数组最后面(LRU)
(2)不存在,将组件 key 放入数组,然后判断当前 key数组是否超过 max 所设置的范围,超过,那么削减未使用时间最长的一个组件的 key
4.最后将这个组件的 keepAlive 设置为 true

(3)keep-alive 本身的创建过程和 patch 过程

缓存渲染的时候,会根据 vnode.componentInstance(首次渲染 vnode.componentInstance 为 undefined) 和 keepAlive 属性判断不会执行组件的 created、mounted 等钩子函数,而是对缓存的组件执行 patch 过程∶ 直接把缓存的 DOM 对象直接插入到目标元素中,完成了数据更新的情况下的渲染过程。
组件的首次渲染∶判断组件的 abstract 属性,才往父组件里面挂载 DOM

// core/instance/lifecycle
function initLifecycle (vm: Component) {const options = vm.$options// locate first non-abstract parentlet parent = options.parentif (parent && !options.abstract) { // 判断组件的abstract属性,才往父组件里面挂载DOMwhile (parent.$options.abstract && parent.$parent) {parent = parent.$parent}parent.$children.push(vm)}vm.$parent = parentvm.$root = parent ? parent.$root : vmvm.$children = []vm.$refs = {}vm._watcher = nullvm._inactive = nullvm._directInactive = falsevm._isMounted = falsevm._isDestroyed = falsevm._isBeingDestroyed = false
}

判断当前 keepAlive 和 componentInstance 是否存在来判断是否要执行组件 prepatch 还是执行创建 componentlnstance

// core/vdom/create-component
init (vnode: VNodeWithData, hydrating: boolean): ?boolean {if (vnode.componentInstance &&!vnode.componentInstance._isDestroyed &&vnode.data.keepAlive) { // componentInstance在初次是undefined!!!// kept-alive components, treat as a patchconst mountedNode: any = vnode // work around flowcomponentVNodeHooks.prepatch(mountedNode, mountedNode) // prepatch函数执行的是组件更新的过程} else {const child = vnode.componentInstance = createComponentInstanceForVnode(vnode,activeInstance)child.$mount(hydrating ? vnode.elm : undefined, hydrating)}},

prepatch 操作就不会在执行组件的 mounted 和 created 生命周期函数,而是直接将 DOM 插入

(4)LRU (least recently used)缓存策略

LRU 缓存策略∶ 从内存中找出最久未使用的数据并置换新的数据。
LRU(Least rencently used)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是 “如果数据最近被访问过,那么将来被访问的几率也更高”。 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下∶

1.新数据插入到链表头部
2.每当缓存命中(即缓存数据被访问),则将数据移到链表头部
3.链表满的时候,将链表尾部的数据丢弃。

相关文章:

在vue中对keep-alive的理解,它是如何实现的,具体缓存的是什么?

对keep-alive的理解&#xff0c;它是如何实现的&#xff0c;具体缓存的是什么&#xff1f; &#xff08;1&#xff09;keep-alive有以下三个属性&#xff1a;注意&#xff1a;keep-alive 包裹动态组件时&#xff0c;会缓存不活动的组件实例。主要流程 &#xff08;2&#xff09…...

章节一、认识three.js与开发环境学习笔记01;

一、如何学习WEB可视化3D技术与课程内容演示&#xff1b; 1、项目案例&#xff1a; 政府有大量的新基建的项目&#xff1a;如数字孪生、智慧城市、智慧园区、智慧工厂、智慧消防等等都涉及了3d的可视化技术&#xff1b; 2、如何系统的学号WEB 3D可视化技术&#xff1f; three…...

QT摄像头采集

主界面为显示框&#xff0c;两个下拉框&#xff0c;一个是所有相机&#xff0c;一个是相机支持的分辨率 系统根据UI界面自动生成的部分不再描述&#xff0c;以下为其他部分源码 widget.h #include <QWidget> #include <QMouseEvent> class QCamera; class QCamer…...

C语言第三十四弹---动态内存管理(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、动态内存经典笔试题分析 1.1、题目1 1.2、题目2 1.3、题目3 1.4、题目4 2、柔性数组 2.1、柔性数组的特点 2.2、柔性数组的使用 2.3、…...

PDN分析及应用系列二-简单5V电源分配-Altium Designer仿真分析-AD

PDN分析及应用系列二 —— 案例1:简单5V电源分配 预模拟DC网络识别 当最初为PCB设计打开PDN分析仪时,它将尝试根据公共电源网络命名法从设计中识别所有直流电源网络。 正确的DC网络识别对于获得最准确的模拟结果非常重要。 在示例项目中已经识别出主DC网络以简化该过程。 …...

Vue开发实例(一)Vue环境搭建第一个项目

Vue环境搭建&第一个项目 一、环境搭建二、安装Vue脚手架三、创建Vue项目 一、环境搭建 下载方式从官网下载&#xff1a;http://nodejs.cn/download/ 建议下载v12.16.0版本以上的&#xff0c;因为版本低无法创建Vue的脚手架 检验是否安装成功 配置环境变量 新增NODE_HOME&…...

将SpringBoot项目改造成solon项目

solon项目介绍 官网 Java “生态型”应用开发框架&#xff1a;更快、更小、更简单。 启动快 5 &#xff5e; 10 倍&#xff1b;并发高 2&#xff5e; 3 倍&#xff1b; 内存省 1/3 ~ 1/2&#xff1b;打包缩到 1/2 ~ 1/10&#xff1b;同时支持 java8, java11, java17, java21&a…...

更详细的软件测试理论基础:流程,开发、测试模型,测试分类,测试用例及其设计方法,缺陷

文章目录 一、测试流程二、开发模型1、 瀑布模型2、增量模型3、快速模型4、其他 三、测试模型1、V模型2、W模型 四、测试分类五、测试用例 test case六、测试用例设计方法1、等价类划分法2、边界值分析法3、因果图法4、判定表法5、正交法6、场景法7、流程分析法8、错误推测法方…...

input css padding

这样控件会跑出外套控件在HTML JSP里面是经常出现的。但有些外国adobe的as控件不存在这种情况&#xff0c;这是因为内层控件定义的时候不能超出外层控件的范围。 修改下&#xff1a;去掉原来css padding&#xff0c;然后加上宽度和高度...

如何打印 springboot 框架中 接收请求的日志

在 Spring Boot 框架中&#xff0c;您可以使用日志来记录接收请求和发送响应的详细信息。Spring Boot 默认使用 SLF4J&#xff08;Simple Logging Facade for Java&#xff09;作为日志抽象层&#xff0c;并支持多种日志实现&#xff0c;如 Logback、Log4j2 等。以下是一种常见…...

JVM的内存区域划分

JVM即Java虚拟机&#xff0c;是Java实现跨平台交互能力的核心&#xff0c;Java编译后的.class文件&#xff0c;就是通过虚拟机和操作系统进行交互的&#xff1b; 常见的虚拟机有&#xff1a;JVM、VMwave、Virtual Box&#xff0c;目前最主流使用的JVM是HotSpot VM&#xff1b;…...

YOLOv9有效改进|使用动态蛇形卷积Dynamic Snake Convolution

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、改进点介绍 使用ICCV2023中的动态蛇形卷积替换YOLOv9网络中的Conv模块。 二、Dynamic Snake Convolution模块详解 2.1 模块简介 应用场景&#x…...

设计模式学习笔记 - 设计原则 - 1.单一职责原则

前言 前面我们提到过 SOLID 原则&#xff0c;实际上 SOLID 由 5 个设计原则组成&#xff0c;分别是&#xff1a;单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖反转原则。它们分别对应 SLOID 中的 S、O、L、I、D 这 5 个英文字母。 今天来学习下 SOLID 原则中的第…...

飞天使-学以致用-devops知识点4-SpringBoot项目CICD实现(实验失败,了解大概流程)

文章目录 代码准备创建jenkins 任务测试推送使用项目里面的jenkinsfile 进行升级操作 文字版本流程项目构建 代码准备 推送代码到gitlab 代码去叩叮狼教育找 k8s 创建jenkins 任务 创建一个k8s-cicd-demo 流水线任务 将jenkins 里面构建时候的地址还有token&#xff0c; 给到…...

使用HTML5画布(Canvas)模拟图层(Layers)效果

使用HTML5画布&#xff08;Canvas&#xff09;模拟图层&#xff08;Layers&#xff09;效果 在图形处理和计算机图形学中&#xff0c;图层&#xff08;Layers&#xff09;是指将图像分成不同的可独立编辑、组合和控制的部分的技术或概念。每个图层都可以包含不同的图形元素、效…...

违背祖训,微软骚操作强制用户更新至 Win 11 23H2

话说&#xff0c;大伙儿有让 Windows 操作系统一直保持最新版习惯吗&#xff1f; 根据以往惯例&#xff0c;Windows 系统更新是个比较玄学的存在&#xff0c;谁也不能保证随手更新后会不会出现什么奇葩 Bug。 因此对于不少同学来说&#xff0c;Windows 更新到一个稳定版本后&a…...

MISRA C++ 2023指南:您需要了解的一切

MISRA C 2023可以帮助使用现代C语言的组织开发安全关键型软件。使用新的MISRA标准&#xff0c;开发人员可以通过确保和记录其软件应用程序的MISRA合规性&#xff0c;满足IEC 6108或ISO 26262等功能安全标准给出的静态分析要求。 什么是MISRA C2023? 以便使用C17进行安全可靠…...

Vue:【亲测可用】父组件数组包对象,传给子组件对象,子组件修改属性(字段)后,父组件没有更新

场景&#xff1a;vue中父组件数组包对象&#xff0c;传给子组件对象&#xff0c;子组件修改属性&#xff08;字段&#xff09;后&#xff0c;父组件没有更新 代码&#xff1a; # 父组件 <div v-for"(object, name, index) in arr" :key"index"><…...

hbase学习十:客户端实现与Meta表解析

1、客户端实现 hbase社区的客户端一般是java客户端。 HBase也支持Shell交互式客户端。Shell客户端实质是用JRuby(用Java编写的Ruby解释器,方便Ruby脚本跑在JVM虚拟机上)脚本调用官方HBase客户端来实现的。因此,各种客户端的核心实现都在社区Java版本客户端上。 客户端访…...

《OpenScene: 3D Scene Understanding with Open Vocabularies》阅读笔记1

传统的3D场景理解方法依赖于带标签的3D数据集,用于训练一个模型以进行单一任务的监督学习。我们提出了OpenScene,一种替代方法,其中模型在CLIP特征空间中预测与文本和图像像素共同嵌入的3D场景点的密集特征。这种零样本方法实现了与任务无关的训练和开放词汇查询。例如,为了…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...