【Vue3】keep-alive 缓存组件

当在 Vue.js 中使用 <keep-alive> 组件时,它将会缓存动态组件,而不是每次渲染都销毁和重新创建它们。这对于需要在组件间快速切换并且保持组件状态的情况非常有用。

<keep-alive> 只能包含(或者说只能渲染)一个子组件,如果需要包含多个子组件,需要用 v-if 选择某个确定的组件进行渲染。也可以使用 <template> 或其他组件标签将它们包裹起来,再通过 v-if 选择确定的某个组件进行渲染。因此 keep-alive 标签里面有且只有一个子节点(或者说只能渲染一个子节点)。这些子组件可以通过动态组件或者其他方式进行切换。

当一个被 <keep-alive> 组件包裹的组件被切换出去时,它的状态将会被保留在内存中,而不会被销毁。当组件再次被切换回来时,它会从缓存中直接取出,并且保持之前的状态。

1. keep-alive 和 v-show 的区别

  • 作用:

<keep-alive>:用于缓存组件,以避免每次组件切换时销毁和重新创建实例。它会保留组件的状态,以便在需要时直接从缓存中取出。

v-show:用于根据条件动态显示或隐藏组件。它通过控制 display CSS 属性来决定组件是否在 DOM 中渲染。

  • 使用场景:

<keep-alive>:适用于需要在组件间快速切换并保持组件状态的场景。例如,当你有一个包含表单的编辑页面,在切换到其他页面并返回时,希望保留用户已输入的数据。

v-show:适用于根据某些条件动态显示或隐藏单个组件。例如,根据用户权限动态显示不同的导航菜单。

  • 对组件实例的影响:

<keep-alive>:保留组件的状态和实例,只是保存虚拟 DOM ,以便在需要时直接从缓存中取出。组件的生命周期钩子函数 activated 和 deactivated 也会在缓存和激活时触发。

v-show:每次切换显示或隐藏时,组件实例会保持不变,存在于真实 DOM ,并且会触发相应的生命周期钩子函数 beforeUpdate 和 updated。

2. keep-alive 使用案例

App.vue

<template><el-button type="primary" @click="flag = !flag"> 切换组件</el-button><!-- [] 里面名称是原本的组件名 --><!-- props介绍::exclude="['A']"  不缓存A组件:include="['A']"  缓存A组件:max="2"  最多缓存2个,如有多个从后往前算起--><keep-alive :exclude="['A']"><AVue v-if="flag"></AVue><B v-else></B></keep-alive></template><script setup lang="ts">
import { ref } from 'vue';
import AVue from './components/A.vue'
import B from './components/B.vue'
const flag = ref<boolean>(true)
</script><style scoped></style>

A.vue

<template><h1 style="margin: 10px;">我是A组件</h1><el-form :model="form" label-width="120px"><el-form-item label="Activity name"><el-input v-model="form.name" /></el-form-item><el-form-item label="Activity zone"><el-select v-model="form.region" placeholder="please select your zone"><el-option label="Zone one" value="shanghai" /><el-option label="Zone two" value="beijing" /></el-select></el-form-item><el-form-item label="Activity time"><el-col :span="11"><el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" /></el-col><el-col :span="2" class="text-center"><span class="text-gray-500">-</span></el-col><el-col :span="11"><el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" /></el-col></el-form-item><el-form-item label="Instant delivery"><el-switch v-model="form.delivery" /></el-form-item><el-form-item label="Activity type"><el-checkbox-group v-model="form.type"><el-checkbox label="Online activities" name="type" /><el-checkbox label="Promotion activities" name="type" /><el-checkbox label="Offline activities" name="type" /><el-checkbox label="Simple brand exposure" name="type" /></el-checkbox-group></el-form-item><el-form-item label="Resources"><el-radio-group v-model="form.resource"><el-radio label="Sponsor" /><el-radio label="Venue" /></el-radio-group></el-form-item><el-form-item label="Activity form"><el-input v-model="form.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">Create</el-button><el-button>Cancel</el-button></el-form-item></el-form>
</template><script lang="ts" setup>
import { reactive } from 'vue'// do not use same name with ref
const form = reactive({name: '',region: '',date1: '',date2: '',delivery: false,type: [],resource: '',desc: '',
})const onSubmit = () => {console.log('submit!')
}
</script>

B.vue

<template><h1 style="margin: 10px;">我是B组件</h1><el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm" :size="formSize"status-icon><el-form-item label="Activity name" prop="name"><el-input v-model="ruleForm.name" /></el-form-item><el-form-item label="Activity zone" prop="region"><el-select v-model="ruleForm.region" placeholder="Activity zone"><el-option label="Zone one" value="shanghai" /><el-option label="Zone two" value="beijing" /></el-select></el-form-item><el-form-item label="Activity count" prop="count"><el-select-v2 v-model="ruleForm.count" placeholder="Activity count" :options="options" /></el-form-item><el-form-item label="Activity time" required><el-col :span="11"><el-form-item prop="date1"><el-date-picker v-model="ruleForm.date1" type="date" label="Pick a date" placeholder="Pick a date"style="width: 100%" /></el-form-item></el-col><el-col class="text-center" :span="2"><span class="text-gray-500">-</span></el-col><el-col :span="11"><el-form-item prop="date2"><el-time-picker v-model="ruleForm.date2" label="Pick a time" placeholder="Pick a time" style="width: 100%" /></el-form-item></el-col></el-form-item><el-form-item label="Instant delivery" prop="delivery"><el-switch v-model="ruleForm.delivery" /></el-form-item><el-form-item label="Activity type" prop="type"><el-checkbox-group v-model="ruleForm.type"><el-checkbox label="Online activities" name="type" /><el-checkbox label="Promotion activities" name="type" /><el-checkbox label="Offline activities" name="type" /><el-checkbox label="Simple brand exposure" name="type" /></el-checkbox-group></el-form-item><el-form-item label="Resources" prop="resource"><el-radio-group v-model="ruleForm.resource"><el-radio label="Sponsorship" /><el-radio label="Venue" /></el-radio-group></el-form-item><el-form-item label="Activity form" prop="desc"><el-input v-model="ruleForm.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button><el-button @click="resetForm(ruleFormRef)">Reset</el-button></el-form-item></el-form>
</template><script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'interface RuleForm {name: stringregion: stringcount: stringdate1: stringdate2: stringdelivery: booleantype: string[]resource: stringdesc: string
}const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({name: '',region: '',count: '',date1: '',date2: '',delivery: false,type: [],resource: '',desc: '',
})const rules = reactive<FormRules<RuleForm>>({name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' },{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },],region: [{required: true,message: 'Please select Activity zone',trigger: 'change',},],count: [{required: true,message: 'Please select Activity count',trigger: 'change',},],date1: [{type: 'date',required: true,message: 'Please pick a date',trigger: 'change',},],date2: [{type: 'date',required: true,message: 'Please pick a time',trigger: 'change',},],type: [{type: 'array',required: true,message: 'Please select at least one activity type',trigger: 'change',},],resource: [{required: true,message: 'Please select activity resource',trigger: 'change',},],desc: [{ required: true, message: 'Please input activity form', trigger: 'blur' },],
})const submitForm = async (formEl: FormInstance | undefined) => {if (!formEl) returnawait formEl.validate((valid, fields) => {if (valid) {console.log('submit!')} else {console.log('error submit!', fields)}})
}const resetForm = (formEl: FormInstance | undefined) => {if (!formEl) returnformEl.resetFields()
}const options = Array.from({ length: 10000 }).map((_, idx) => ({value: `${idx + 1}`,label: `${idx + 1}`,
}))
</script>


在这里插入图片描述

3. 因注释导致的意外错误

写入注释:
在这里插入图片描述

报错:
在这里插入图片描述
因此 keep-alive 组件内不要使用注释,会被解析为子节点

解决方法:

  • keep-alive 内部不写注释

  • 使用 <template> 或其他组件标签将它们包裹起来

    • 此时 可以认为 利用了 keep-alive 标签里面有且只有一个子节点(或者说只能渲染一个子节点)
  <keep-alive :exclude="['A']"><template v-if="flag"><!-- [] 里面名称是原本的组件名 --><AVue></AVue></template><template v-else><B></B></template></keep-alive>

4. keep-alive 生命周期

<keep-alive> 组件提供了以下两个主要的生命周期钩子函数来管理缓存的组件:

  • activated:被缓存的组件激活时调用。

  • deactivated:被缓存的组件停用时调用。

App.vue

<template><el-button type="primary" @click="flag = !flag"> 切换组件</el-button><!-- props介绍::exclude="['A']"  不缓存A组件:include="['A']"  缓存A组件:max="2"  最多缓存2个,如有多个从后往前算起--><keep-alive :exclude="['B']"><AVue v-if="flag"></AVue><B v-else></B></keep-alive>
</template><script setup lang="ts">
import { ref } from 'vue';
import AVue from './components/A.vue'
import B from './components/B.vue'const flag = ref<boolean>(true)
</script><style scoped></style>

A.vue

<template><h1 style="margin: 10px;">我是A组件</h1><el-form :model="form" label-width="120px"><el-form-item label="Activity name"><el-input v-model="form.name" /></el-form-item><el-form-item label="Activity zone"><el-select v-model="form.region" placeholder="please select your zone"><el-option label="Zone one" value="shanghai" /><el-option label="Zone two" value="beijing" /></el-select></el-form-item><el-form-item label="Activity time"><el-col :span="11"><el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" /></el-col><el-col :span="2" class="text-center"><span class="text-gray-500">-</span></el-col><el-col :span="11"><el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" /></el-col></el-form-item><el-form-item label="Instant delivery"><el-switch v-model="form.delivery" /></el-form-item><el-form-item label="Activity type"><el-checkbox-group v-model="form.type"><el-checkbox label="Online activities" name="type" /><el-checkbox label="Promotion activities" name="type" /><el-checkbox label="Offline activities" name="type" /><el-checkbox label="Simple brand exposure" name="type" /></el-checkbox-group></el-form-item><el-form-item label="Resources"><el-radio-group v-model="form.resource"><el-radio label="Sponsor" /><el-radio label="Venue" /></el-radio-group></el-form-item><el-form-item label="Activity form"><el-input v-model="form.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">Create</el-button><el-button>Cancel</el-button></el-form-item></el-form>
</template><script lang="ts" setup>
import { reactive,onMounted,onUnmounted,onDeactivated,onActivated } from 'vue'// do not use same name with ref
const form = reactive({name: '',region: '',date1: '',date2: '',delivery: false,type: [],resource: '',desc: '',
})const onSubmit = () => {console.log('submit!')
}onMounted(() => {console.log('初始化')
}),
onActivated(() => {console.log('keep-alive初始化')
})
onDeactivated(() => {console.log('keep-alive销毁')
})
onUnmounted(() => {console.log('销毁')
})
</script>

B.vue

<template><h1 style="margin: 10px;">我是B组件</h1><el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm" :size="formSize"status-icon><el-form-item label="Activity name" prop="name"><el-input v-model="ruleForm.name" /></el-form-item><el-form-item label="Activity zone" prop="region"><el-select v-model="ruleForm.region" placeholder="Activity zone"><el-option label="Zone one" value="shanghai" /><el-option label="Zone two" value="beijing" /></el-select></el-form-item><el-form-item label="Activity count" prop="count"><el-select-v2 v-model="ruleForm.count" placeholder="Activity count" :options="options" /></el-form-item><el-form-item label="Activity time" required><el-col :span="11"><el-form-item prop="date1"><el-date-picker v-model="ruleForm.date1" type="date" label="Pick a date" placeholder="Pick a date"style="width: 100%" /></el-form-item></el-col><el-col class="text-center" :span="2"><span class="text-gray-500">-</span></el-col><el-col :span="11"><el-form-item prop="date2"><el-time-picker v-model="ruleForm.date2" label="Pick a time" placeholder="Pick a time" style="width: 100%" /></el-form-item></el-col></el-form-item><el-form-item label="Instant delivery" prop="delivery"><el-switch v-model="ruleForm.delivery" /></el-form-item><el-form-item label="Activity type" prop="type"><el-checkbox-group v-model="ruleForm.type"><el-checkbox label="Online activities" name="type" /><el-checkbox label="Promotion activities" name="type" /><el-checkbox label="Offline activities" name="type" /><el-checkbox label="Simple brand exposure" name="type" /></el-checkbox-group></el-form-item><el-form-item label="Resources" prop="resource"><el-radio-group v-model="ruleForm.resource"><el-radio label="Sponsorship" /><el-radio label="Venue" /></el-radio-group></el-form-item><el-form-item label="Activity form" prop="desc"><el-input v-model="ruleForm.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button><el-button @click="resetForm(ruleFormRef)">Reset</el-button></el-form-item></el-form>
</template><script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'interface RuleForm {name: stringregion: stringcount: stringdate1: stringdate2: stringdelivery: booleantype: string[]resource: stringdesc: string
}const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({name: '',region: '',count: '',date1: '',date2: '',delivery: false,type: [],resource: '',desc: '',
})const rules = reactive<FormRules<RuleForm>>({name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' },{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },],region: [{required: true,message: 'Please select Activity zone',trigger: 'change',},],count: [{required: true,message: 'Please select Activity count',trigger: 'change',},],date1: [{type: 'date',required: true,message: 'Please pick a date',trigger: 'change',},],date2: [{type: 'date',required: true,message: 'Please pick a time',trigger: 'change',},],type: [{type: 'array',required: true,message: 'Please select at least one activity type',trigger: 'change',},],resource: [{required: true,message: 'Please select activity resource',trigger: 'change',},],desc: [{ required: true, message: 'Please input activity form', trigger: 'blur' },],
})const submitForm = async (formEl: FormInstance | undefined) => {if (!formEl) returnawait formEl.validate((valid, fields) => {if (valid) {console.log('submit!')} else {console.log('error submit!', fields)}})
}const resetForm = (formEl: FormInstance | undefined) => {if (!formEl) returnformEl.resetFields()
}const options = Array.from({ length: 10000 }).map((_, idx) => ({value: `${idx + 1}`,label: `${idx + 1}`,
}))
</script>

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CANoe通过Frame Histogram窗口统计报文周期(方便快捷)

文章目录 效果展示1.插入Frame Histogram窗口2.Activate3.运行CANoe&#xff0c;停止后查看write窗口 效果展示 统计报文周期信息输出在write窗口。 1.插入Frame Histogram窗口 2.Activate 3.运行CANoe&#xff0c;停止后查看write窗口 统计报文周期信息输出在write窗口。

04-2_Qt 5.9 C++开发指南_SpinBox使用

文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入&#xff0c;一般显示十进制数&#xff0c;也可以显示二进制、十六进制的数&#xff0c;而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…

机器学习笔记:李宏毅ChatGPT课程1:刨析ChatGPT

ChatGPT——Chat Generative Pre-trained Transformer 1 文字接龙 每次输出一个概率分布&#xff0c;根据概率sample一个答案 ——>因为是根据概率采样&#xff0c;所以ChatGPT每次的答案是不一样的&#xff08;把生成式学习拆分成多个分类问题&#xff09;将生成的答案加到…

Linux(进程)

Linux&#xff08;进程&#xff09; 1. 冯诺依曼结构体系2 . 操作系统&#xff08;OS&#xff09;3.进程task_ struct内容分类查看进程查看PID以及PPIDfork()Linux操作系统进程的状态僵尸进程孤儿进程进程优先级其他概念 1. 冯诺依曼结构体系 冯诺依曼结构也称普林斯顿结构&am…

ArcGIS、ENVI、InVEST、FRAGSTATS技术教程

专题一 空间数据获取与制图 1.1 软件安装与应用讲解 1.2 空间数据介绍 1.3海量空间数据下载 1.4 ArcGIS软件快速入门 1.5 Geodatabase地理数据库 专题二 ArcGIS专题地图制作 2.1专题地图制作规范 2.2 空间数据的准备与处理 2.3 空间数据可视化&#xff1a;地图符号与注…

机器学习、深度学习项目开发业务数据场景梳理汇总记录二

本文的主要作用是对历史项目开发过程中接触到的业务数据进行整体的汇总梳理&#xff0c;文章会随着项目的开发推进不断更新。 这里是续文&#xff0c;因为CSDN单篇文章内容太大的话就会崩溃的&#xff0c;别问我怎么知道的&#xff0c;问就是血泪教训&#xff0c;辛辛苦苦写了一…

泰国的区块链和NFT市场调研

泰国的区块链和NFT市场调研 基本介绍 参考&#xff1a; https://zh.wikipedia.org/zh-hans/%E6%B3%B0%E5%9B%BD参考&#xff1a; https://hktdc.infogram.com/thsc–1h7k2303zo75v2x zz制度&#xff1a; 君主立宪制&#xff08;议会制&#xff09; 国王&#xff1a; 玛哈哇集拉…

如何给Google Chrome增加proxy

1. 先打开https://github.com/KaranGauswami/socks-to-http-proxy/releases 我的电脑是Liunx系统所以下载第一个 2. 下载完之后把这个文件变成可执行文件&#xff0c;可以是用这个命令 chmod x 文件名 3. 然后执行这个命令&#xff1a; ./sthp-linux -p 8080 -s 127.0.0.1:…

HTTP协议

HTTP协议 应用层再谈 "协议"网络版计算器 HTTP协议认识URLurlencode和urldecodeHTTP协议格式HTTP的方法HTTP的状态码HTTP常见Header HTTPS协议HTTPS 是什么什么是"加密"为什么要加密常⻅的加密⽅式 HTTPS 的⼯作过程探究⽅案 1 - 只使⽤对称加密⽅案 2 - 只…

HBase-读流程

创建连接同写流程。 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;3&#xff09;ZK正常返回Meta表所在位置&#x…

企业权限管理(五)-订单分页

订单分页查询 PageHelper介绍 PageHelper是国内非常优秀的一款开源的mybatis分页插件&#xff0c;它支持基本主流与常用的数据库&#xff0c;例如mysql、oracle、mariaDB、DB2、SQLite、Hsqldb等。 PageHelper使用 集成 引入分页插件有下面2种方式&#xff0c;推荐使用 Maven …

什么是Linux,如何在Windows操作系统下搭建Linux环境,远程连接Linux系统

文章目录 什么是LinuxLinux的诞生及发展为什么要学习LinuxLinux内核Linux发行版什么是虚拟机如何在VMware虚拟机中搭建Linux系统环境远程连接 Linux 系统Linux 帮助网站 什么是Linux Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和UNIX的多用户…

Celery的基本使用

1.Celery介绍 1.1 Celery是什么&#xff1f; Celery是Python开发的简单、灵活可靠的、处理大量消息的分布式任务调度模块专注于实时处理的异步任务队列同时也支持任务调度 Celery本身不含消息服务&#xff0c;它使用第三方消息服务来传递任务&#xff0c;目前&#xff0c;Ce…

无涯教程-Perl - 格式化

Perl使用称为“formats”的模板来输出内容。要使用Perl的格式函数&#xff0c;必须先定义一种格式&#xff0c;然后才能使用该格式写入格式化的数据。 定义格式 以下是定义Perl格式的语法- format FormatName fieldline value_one, value_two, value_three fieldline value…

图像的平移变换之c++实现(qt + 不调包)

1.基本原理 设dx为水平偏移量&#xff0c;dy为垂直偏移量&#xff0c;则平移变换的坐标映射关系为下公式&#xff0c;图像平移一般有两种方式。 1.不改变图像大小的平移&#xff08;一旦平移&#xff0c;相应内容被截掉&#xff09; 1&#xff09;当dx > width、dx < -wi…

(MVC)SpringBoot+Mybatis+Mapper.xml

前言&#xff1a;本篇博客主要对MVC架构、Mybatis工程加深下理解&#xff0c;前面写过一篇博客&#xff1a;SprintBoothtml/css/jsmybatis的demo&#xff0c;里面涉及到了Mybatis的应用&#xff0c;此篇博客主要介绍一种将sql语句写到了配置文件里的方法&#xff0c;即Mybatis里…

vue去掉所有输入框两边空格,封装指令去空格,支持Vue2和Vue3,ElementUI Input去空格

需求背景 就是页面很多表单输入框&#xff0c;期望在提交的时候&#xff0c;都要把用户两边的空格去掉 ❌使用 vue 的指令 .trim 去掉空格 中间会输入不了空格&#xff0c; 比如我想输入 你好啊 中国, 这中间的空格输入不了&#xff0c;只能变成 你好啊中国 ❌在提交的时候使用…

cesium学习记录04-坐标系

一、地理坐标系和投影坐标系的关系 地理坐标系 (Geographic Coordinate System, GCS) 定义&#xff1a;地理坐标系是一个基于三维地球表面的坐标系统。它使用经度和纬度来表示地点的位置。 特点&#xff1a; 使用经纬度来定义位置。 基于特定的地球参考椭球体。 适用于全球范…

设备固定资产管理系统

资产管理是企业经营和发展的基础&#xff0c;特别是设备资产管理。适当的设备资产管理可以有效地提升企业的经营效率&#xff0c;为提高核心竞争能力提供高效的前提。 固资及设备管理系统&#xff08;EAM&#xff09;它是一种有效的固定资产管理模式&#xff0c;可以帮助企业更…

gradle 命令行单元测试执行问题

文章目录 问题&#xff1a;命令行 执行失败最终解决方案&#xff08;1&#xff09;ADB命令&#xff08;2&#xff09;Java 环境配置 问题&#xff1a;命令行 执行失败 命令行 执行测试命令 无法使用&#xff08;之前还能用的。没有任何改动&#xff0c;又不能用了&#xff09; …