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

详细分析KeepAlive的基本知识 并缓存路由(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
    • 2.1 基本
    • 2.2 拓展
    • 2.3 终极
  • 3. 实战

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

基本知识推荐阅读:KeepAlive知识点

从实战中学习,源自实战中vue路由的缓存设置

<router-view v-if="routerAlive"><template #default="{ Component, route }"><keep-alive :include="getCaches"><component :is="Component" :key="route.fullPath" /></keep-alive></template>
</router-view>

截图如下:

在这里插入图片描述

1. 基本知识

<KeepAlive> 内置组件,用于缓存动态组件或路由组件,以提高性能
可以保留组件的状态,避免重复渲染和生命周期钩子的重新调用

KeepAlive 作用

  • 缓存组件,提高性能,避免组件反复销毁和创建
  • 保留组件的状态,例如表单填写内容、滚动位置等
  • 控制缓存,可以指定哪些组件需要被缓存,哪些不需要

KeepAlive 适用场景

  • 需要缓存的 多页面表单
  • 列表详情页切换 时,保留列表的滚动位置
  • 复杂组件切换时,避免重新渲染带来的性能开销
功能说明
KeepAlive用于缓存组件,提高性能
include指定要缓存的组件(支持字符串或数组)
exclude指定不缓存的组件
max限制最大缓存组件数量
activated()组件被激活时触发
deactivated()组件被缓存时触发

include 和 exclude
可以通过 include 和 exclude 来决定哪些组件需要被缓存,哪些不需要

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

只有 ComponentA 会被缓存,而 ComponentB 不会

或者:

<keep-alive :include="['ComponentA', 'ComponentC']"><component :is="currentComponent"></component>
</keep-alive>

只有 ComponentA 和 ComponentC 会被缓存
如果需要排除某个组件:

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

ComponentB 不会被缓存,而其他组件都会被缓存

max —— 设置缓存组件的最大数量
如果缓存的组件较多,可以设置 max 限制最多缓存多少个组件
只缓存最近的两个组件,超出的组件会被销毁

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

KeepAlive 生命周期钩子
Vue 提供了两个专门用于 KeepAlive 组件的生命周期钩子:
activated():组件被激活(切换到缓存中的组件时调用)
deactivated():组件被缓存(切换到另一个组件时调用)

<script>
export default {created() {console.log("组件创建");},activated() {console.log("组件被激活");},deactivated() {console.log("组件被缓存");},destroyed() {console.log("组件被销毁");},
};
</script>

运行效果:

  1. 组件首次渲染时,created() 会触发
  2. 当组件切换回来时,activated() 会触发,而不会重新执行 created()
  3. 切换到别的组件时,deactivated() 触发,而不会执行 destroyed()
  4. 只有当缓存被清除时,才会执行 destroyed()

2. Demo

2.1 基本

动态组件缓存

<template><div><button @click="currentComponent = 'ComponentA'">切换到A</button><button @click="currentComponent = 'ComponentB'">切换到B</button><keep-alive><component :is="currentComponent"></component></keep-alive></div>
</template><script>
import ComponentA from "./ComponentA.vue";
import ComponentB from "./ComponentB.vue";export default {data() {return {currentComponent: "ComponentA",};},components: {ComponentA,ComponentB,},
};
</script>

组件 A (ComponentA.vue):

<template><div><h3>组件 A</h3><input v-model="text" placeholder="输入内容会被缓存" /></div>
</template><script>
export default {data() {return {text: "",};},created() {console.log("ComponentA 创建");},destroyed() {console.log("ComponentA 被销毁");},
};
</script>

组件 B (ComponentB.vue):

<template><div><h3>组件 B</h3></div>
</template><script>
export default {created() {console.log("ComponentB 创建");},destroyed() {console.log("ComponentB 被销毁");},
};
</script>

一个最明显的变化就是:
在 ComponentA 中输入一些文字,然后切换到 ComponentB,再切回来,发现输入内容还在(ComponentA 没有被销毁)

2.2 拓展

KeepAlive 也可以与 Vue Router 结合,缓存路由组件
这样在 PageA 和 PageB 之间切换时,PageA 不会被销毁,而是会被缓存

<template><div><router-link to="/pageA">页面 A</router-link><router-link to="/pageB">页面 B</router-link><keep-alive><router-view></router-view></keep-alive></div>
</template>

路由配置:

import { createRouter, createWebHistory } from "vue-router";
import PageA from "./PageA.vue";
import PageB from "./PageB.vue";const routes = [{ path: "/pageA", component: PageA },{ path: "/pageB", component: PageB },
];const router = createRouter({history: createWebHistory(),routes,
});export default router;

2.3 终极

这也是实战中常用的一种方式,从实战中抽离出基本的Demo,以 Vue 3 + Vue Router 4 + Pinia

装依赖:npm install vue-router@4 pinia

main.ts(应用入口)

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Home from './views/Home.vue'
import About from './views/About.vue'
import Profile from './views/Profile.vue'const pinia = createPinia()// 定义路由
const routes = [{ path: '/', component: Home, name: 'Home' },{ path: '/about', component: About, name: 'About' },{ path: '/profile', component: Profile, name: 'Profile' }
]const router = createRouter({history: createWebHistory(),routes
})const app = createApp(App)
app.use(pinia)
app.use(router)
app.mount('#app')

store/tagsView.ts(Pinia 状态管理 - 维护缓存组件列表)

import { defineStore } from 'pinia'export const useTagsViewStore = defineStore('tagsView', {state: () => ({cachedViews: new Set<string>()}),getters: {getCachedViews(): string[] {return Array.from(this.cachedViews)}},actions: {addCachedView(name: string) {this.cachedViews.add(name)},removeCachedView(name: string) {this.cachedViews.delete(name)},clearCachedViews() {this.cachedViews.clear()}}
})

App.vue(KeepAlive 组件封装)

<script setup lang="ts">
import { computed, ref, provide, nextTick } from 'vue'
import { useTagsViewStore } from './store/tagsView'
import { RouterView } from 'vue-router'const tagsViewStore = useTagsViewStore()
const getCaches = computed(() => tagsViewStore.getCachedViews)// 无感刷新功能
const routerAlive = ref(true)
const reload = () => {routerAlive.value = falsenextTick(() => (routerAlive.value = true))
}
provide('reload', reload)
</script><template><div><router-view v-if="routerAlive"><template #default="{ Component, route }"><keep-alive :include="getCaches"><component :is="Component" :key="route.fullPath" /></keep-alive></template></router-view></div>
</template>

views/Home.vue

<script setup lang="ts">
import { inject } from 'vue'const reload = inject('reload') as () => void
</script><template><div><h1>Home Page</h1><button @click="reload">刷新当前组件</button></div>
</template>

views/About.vue

<template><div><h1>About Page</h1></div>
</template>

views/Profile.vue

<template><div><h1>Profile Page</h1></div>
</template>

动态路由的常用操作

  1. 动态添加路由
    在 router.ts 中可以动态添加路由:
import router from './router'const newRoute = {path: '/new-page',component: () => import('@/views/NewPage.vue'),name: 'NewPage'
}router.addRoute(newRoute)
  1. 动态移除路由:router.removeRoute('NewPage')

  2. 监听路由变化

import { useRoute, useRouter } from 'vue-router'
import { watch } from 'vue'const route = useRoute()
const router = useRouter()watch(() => route.fullPath, (newPath) => {console.log('路由发生变化:', newPath)
})

3. 实战

以ruoyi-vue-pro实战的Demo进行讲解,源码:芋道源码/ruoyi-vue-pro

具体KeepAlive,其文件在App.vue中

<router-view v-if="routerAlive"><template #default="{ Component, route }"><keep-alive :include="getCaches"><component :is="Component" :key="route.fullPath" /></keep-alive></template>
</router-view>

通过组件的设置是否路由进行缓存,后续获取到这个路由信息时,对应判定是否该路由有缓存信息

const getCaches = computed((): string[] => {const caches = tagsViewStore.getCachedViewsconsole.log('当前缓存的组件:', caches) // 打印缓存的组件名称return caches
})const tagsView = computed(() => appStore.getTagsView)//region 无感刷新
const routerAlive = ref(true)
// 无感刷新,防止出现页面闪烁白屏
const reload = () => {routerAlive.value = falsenextTick(() => (routerAlive.value = true))
}
// 为组件后代提供刷新方法
provide('reload', reload)

对应的tagsView信息如下:
在这里插入图片描述

后续在tsx中进行引用
在这里插入图片描述

后续新增路由的时候,其路由地址 要和 defineOptions({ name: 'xxx' }) 对应一致

相关文章:

详细分析KeepAlive的基本知识 并缓存路由(附Demo)

目录 前言1. 基本知识2. Demo2.1 基本2.2 拓展2.3 终极 3. 实战 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 基本知识推荐阅读&#xff1a;KeepAlive知识点 从实战中学习&#xff0c;源自实战中vue路由的…...

AI数据分析:deepseek生成SQL

在当今数据驱动的时代&#xff0c;数据分析已成为企业和个人决策的重要工具。随着人工智能技术的快速发展&#xff0c;AI 驱动的数据分析工具正在改变我们处理和分析数据的方式。本文将着重介绍如何使用 DeepSeek 进行自动补全SQL 查询语句。 我们都知道&#xff0c;SQL 查询语…...

Kafka 消息 0 丢失的最佳实践

文章目录 Kafka 消息 0 丢失的最佳实践生产者端的最佳实践使用带有回调的 producer.send(msg, callback) 方法设置 acks all设置 retries 为一个较大的值启用幂等性与事务&#xff08;Kafka 0.11&#xff09;正确关闭生产者与 flush() 方法 Broker 端的最佳实践设置 unclean.l…...

vue3(笔记)3.0 Pinia状态管理数据.持久化插件.内置vue devtools调试工具

---pinia状态管理数据(vuex升级版) 官网镜像:(https://pinia.vuejs.org/zh/core-concepts/) 安装(手动): npm install pinia 导入pinia: 组合式写法的格式: 使用前需要导入: import {defineStore} from piniaactions:支持了同步和异步的方法(融合了mutations) 在组件中调…...

装饰器模式:灵活扩展对象功能的利器

一、从咖啡加料说起&#xff1a;什么是装饰器模式&#xff1f; 假设您走进咖啡馆点单&#xff1a; 基础款&#xff1a;美式咖啡&#xff08;15元&#xff09;加料需求&#xff1a;加牛奶&#xff08;3元&#xff09;、加焦糖&#xff08;5元&#xff09;、加奶油&#xff08;…...

linux应用:errno、perror、open、fopen

errno errno 是一个全局变量&#xff0c;定义在 头文件中。当系统调用&#xff08;如 open、read、write 等&#xff09;或库函数执行失败时&#xff0c;会将一个错误码赋值给 errno。不同的错误码代表不同的错误类型&#xff0c;通过检查 errno 的值&#xff0c;可以判断具体…...

网络原理--HTTP协议

http中文名为超文本传输协议&#xff0c;所谓“超文本”就是指传输范围超出了能在UTF8等码表上找到的字符的范围&#xff0c;包含一些图片&#xff0c;特殊格式之类的。 HTTP的发展简介 从图中可以看出到现在已经发展出了HTTP3&#xff0c;但是市面上的主流还是以HTTP1.0为主。…...

编译可以在Android手机上运行的ffmpeg程序

下载代码 git clone gitgithub.com:FFmpeg/FFmpeg.git git checkout n7.0建立build目录 mkdir build cd build创建build.sh脚本 vim build.sh这段脚本的主要功能是配置和编译 FFmpeg&#xff0c;使其能够在 Android 平台上运行&#xff0c;通过设置不同的架构和 API 级别&am…...

华为hcia——Datacom实验指南——配置手工模式以太网链路聚合

什么是以太网链路聚合&#xff08;Eth-trunk&#xff09; 是一种将多个物理链路捆绑在一起&#xff0c;让设备以为是一条大链路&#xff0c;能够增加带宽&#xff0c;增加冗余度&#xff0c;提升可靠性&#xff0c;实现负载平衡。 传输方式有两种 基于数据流传输和基于数据包…...

【C语言6】数组和函数实践:扫雷游戏的简单实现

文章目录 一、扫雷游戏分析和设计1.1 扫雷游戏的功能说明1.2 游戏的分析和设计1.2.1 数据结构的分析1.2.2 文件结构设计 二、扫雷游戏的代码实现三、扫雷游戏的扩展总结 一、扫雷游戏分析和设计 1.1 扫雷游戏的功能说明 使用控制台实现经典的扫雷游戏游戏可以通过菜单实现继续…...

LeetCode 热题 100----1.两数之和

LeetCode 热题 100----1.两数之和 题目描述 我的解法 语言&#xff1a;js 思路就是&#xff1a;用双重循环去找哪两个数字相加等于target&#xff0c;目前的时间复杂度为O(n2)&#xff0c;之后右优化思路再更新。...

《模式和状态管理》知识总结三-EcuM与BswM模块的交互

前言 这篇文章主要搞清楚在模式管理中&#xff0c;BswM和EcuM各自的分工。距离学完模式管理也有几天时间了&#xff0c;写这篇文章算是复习一下。 EcuM及BswM交互总览 EcuM负责Ecu的上下电状态的处理&#xff0c;当Ecu处于正常运行状态的时候&#xff0c;EcuM会将Ecu的控制权…...

RK3568平台(网络篇)RTL8111网卡

RTL8111 是 Realtek 推出的一款高性能千兆以太网控制器芯片,广泛应用于 PCIE 网卡中。 其工作原理涉及 数据链路层 和 物理层 的协同工作,以下是其核心原理的详细说明: 一.网卡的基本功能 1.数据封装与解封装: 网卡负责将计算机中的数据封装成网络传输的帧(Frame),并…...

客户需求模糊或频繁变更怎么办

应对客户需求模糊或频繁变更的关键在于 明确沟通、敏捷应对、科学决策。其中&#xff0c;明确沟通尤为重要&#xff0c;因为通过有效沟通&#xff0c;不仅能迅速厘清客户真实需求&#xff0c;还能及时发现隐藏问题&#xff0c;降低项目风险&#xff0c;为后续调整提供有力数据支…...

动静态库-Linux 学习

在软件开发中&#xff0c;程序库是一组预先编写好的程序代码&#xff0c;它们存储了常用的函数、变量和数据结构等。这些库可以帮助开发者节省大量的时间和精力&#xff0c;避免重复编写相同的代码。当我们在 Linux 系统中开发程序时&#xff0c;经常会用到两种类型的程序库&am…...

DeepSeek 系列模型:论文精读《A Survey of DeepSeek Models》

引言&#xff1a;一篇快速了解 DeepSeek 系列的论文。我在翻译时加入了一些可以提高 “可读性” 的连词 ✅ NLP 研 2 选手的学习笔记 笔者简介&#xff1a;Wang Linyong&#xff0c;NPU&#xff0c;2023级&#xff0c;计算机技术 研究方向&#xff1a;文本生成、大语言模型 论文…...

Python解决“找出整形数组中占比超过一半的数”问题

这里写目录标题 问题描述测试样例解决思路代码法1法2 问题描述 小R从班级中抽取了一些同学&#xff0c;每位同学都会给出一个数字。已知在这些数字中&#xff0c;某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。 测试样例 样例1&#xff1a; 输入&…...

机器人学习模拟框架 robosuite (3) 机器人控制代码示例

Robosuite框架是一个用于机器人模拟和控制的强大工具&#xff0c;支持多种类型的机器人。 官方文档&#xff1a;Overview — robosuite 1.5 documentation 开源地址&#xff1a;https://github.com/ARISE-Initiative/robosuite 目录 1、通过键盘或SpaceMouse远程控制机器人…...

kakfa-3:ISR机制、HWLEO、生产者、消费者、核心参数负载均衡

1. kafka内核原理 1.1 ISR机制 光是依靠多副本机制能保证Kafka的高可用性&#xff0c;但是能保证数据不丢失吗&#xff1f;不行&#xff0c;因为如果leader宕机&#xff0c;但是leader的数据还没同步到follower上去&#xff0c;此时即使选举了follower作为新的leader&#xff…...

【微知】如何查看Mellanox网卡上的光模块的信息?(ethtool -m enp1s0f0 看型号、厂商、生产日期等)

背景 服务器上插入的光模块经常被忽略&#xff0c;往往这里是定位问题最根本的地方。如何通过命令查看&#xff1f; 命令 ethtool提供了-m参数&#xff0c;m是module-info的意思&#xff0c;他是从光模块的eeprom中读取数据。&#xff08;应该是用i2c协议读取的&#xff09;…...

yum源选要配置华为云的源,阿里云用不了的情况

curl -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo...

nginx accesslog 打印自定义header

比如我在请求的header中添加了一个path-match-type&#xff0c;那我现在nginx的accesslog 中打印出来&#xff0c;应该如何配置呢&#xff1f; rootnginx-59f5d66df6-jw5k8:/# cat /etc/nginx/nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/erro…...

好数——前缀和思想(题目分享)

今天我的舍友去参加“传智杯”广东省的省赛&#xff0c;跟我说了这样一道题&#xff0c;他说他想不出来怎么去优化代码&#xff0c;怎么做都是套用两层for循环超时&#xff0c;下面我就根据题意&#xff0c;使用前缀和的算法去优化一下思路&#xff0c;题目本身是不难的&#x…...

MWC 2025 | 移远通信大模型解决方案加速落地,引领服务机器人创新变革

随着人工智能、大模型等技术的蓬勃发展&#xff0c;生成式AI应用全面爆发。在此背景下&#xff0c;服务机器人作为大模型技术在端侧落地的关键场景&#xff0c;迎来了前所未有的发展机遇。 作为与用户直接交互的智能设备&#xff0c;服务机器人需要应对复杂场景下的感知、决策和…...

【大模型基础_毛玉仁】0.概述

更多内容&#xff1a;XiaoJ的知识星球 【大模型基础_毛玉仁】 系列文章参考 系列文章 【大模型基础_毛玉仁】0.概述 【大模型基础_毛玉仁】1.1 基于统计方法的语言模型 更新中。。。。。。 参考 书籍&#xff1a;大模型基础_完整版.pdf Github&#xff1a;https://github.co…...

ADB、Appium 和 大模型融合开展移动端自动化测试

将 ADB、Appium 和 大模型(如 GPT、LLM) 结合,可以显著提升移动端自动化测试的智能化水平和效率。以下是具体的实现思路和应用场景: 1. 核心组件的作用 ADB(Android Debug Bridge): 用于与 Android 设备通信,执行设备操作(如安装应用、获取日志、截图等)。Appium: 用…...

springboot425-基于SpringBoot的BUG管理系统(源码+数据库+纯前后端分离+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…...

Ubuntu系统上部署Node.js项目的完整流程

以下是在Ubuntu系统上部署Node.js项目的完整流程&#xff0c;分为系统初始化、环境配置、项目部署三个部分&#xff1a; 一、系统初始化 & 环境准备 bash # 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y# 2. 安装基础工具 sudo apt install -y buil…...

X Window---图形接口

摘抄自 鸟哥的linux私房菜 基础篇 第四版 有鉴于图形用户接口(Graphical User Interface, GUI) 的需求日益加重&#xff0c;在 1984 年由 MIT 与其他第三方首次发表了 X Window System &#xff0c;并且更在 1988 年成立了非营利性质的 XFree86 这个组织。所谓的XFree86 其实是…...

数据序列化协议 Protobuf 3 介绍(Go 语言)

Protobuf 3 入门 1. 什么是序列化&#xff1f; 1.1 概念 序列化&#xff08;Serialization 或 Marshalling&#xff09; 是指将数据结构或对象的状态转换成可存储或传输的格式。反向操作称为反序列化&#xff08;Deserialization 或 Unmarshalling&#xff09;&#xff0c;它…...