详细分析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 = false
  nextTick(() => (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.getCachedViews
  console.log('当前缓存的组件:', caches) // 打印缓存的组件名称
  return caches
})

const tagsView = computed(() => appStore.getTagsView)

//region 无感刷新
const routerAlive = ref(true)
// 无感刷新,防止出现页面闪烁白屏
const reload = () => {
  routerAlive.value = false
  nextTick(() => (routerAlive.value = true))
}
// 为组件后代提供刷新方法
provide('reload', reload)

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Free Auto Clicker - 在任意位置自动重复鼠标点击

“想让鼠标自己动起来&#xff0c;解放双手去做更有趣的事&#xff1f;”Free Auto Clicker 就像你的数字小助手&#xff0c;能在任意位置自动重复点击鼠标。从玩游戏到刷网页&#xff0c;这款免费工具让你告别枯燥的重复操作&#xff0c;效率瞬间起飞&#xff01; 你有没有想…

【人工智能】GPT-4 vs DeepSeek-R1:谁主导了2025年的AI技术竞争?

前言 2025年&#xff0c;人工智能技术将迎来更加激烈的竞争。随着OpenAI的GPT-4和中国初创公司DeepSeek的DeepSeek-R1在全球范围内崭露头角&#xff0c;AI技术的竞争格局开始发生变化。这篇文章将详细对比这两款AI模型&#xff0c;从技术背景、应用领域、性能、成本效益等多个方…

蓝桥杯第15届真题解析

由硬件框图可以知道我们要配置LED 和按键、lcd&#xff0c;解决lcd引脚冲突 LED 先配置LED的八个引脚为GPIO_OutPut&#xff0c;锁存器PD2也是&#xff0c;然后都设置为起始高电平&#xff0c;生成代码时还要去解决引脚冲突问题 按键 按键配置&#xff0c;由原理图按键所对引…

51c自动驾驶~合集22

我自己的原文哦~ https://blog.51cto.com/whaosoft/11870502 #自动驾驶数据闭环最前沿论文 近几年&#xff0c;自动驾驶技术的发展日新月异。从ECCV 2020的NeRF问世再到SIGGRAPH 2023的3DGS&#xff0c;三维重建走上了快速发展的道路&#xff01;再到自动驾驶端到端技术的…

【Python】——使用python实现GUI图书管理系统:Tkinter+SQLite实战

本文将通过一个完整的python项目——图书管理系统&#xff0c;演示如何利用Tkinter构建GUI 界面&#xff0c;结合SQLite数据库实现增删改查功能。代码简洁易懂&#xff0c;适合python初学者学习和二次开发。 一、项目功能概览 图书管理&#xff1a;添加、查看、修改、删除图书…

Docker创建自定义网桥并指定网段

前言 docker0是Docker默认网络的核心组件, 通过虚拟网桥和NAT技术, 实现了容器间的通信以及容器与外部网络的交互。然而, docker0网段是固定的(通常是172.17.0.0/16), 为了更灵活地管理容器网络&#xff0c;Docker支持创建自定义网桥&#xff0c;允许用户指定网段。 例如, 在…

Spring Boot集成Spring Ai框架【详解 搭建Spring Ai项目,以及简单的ai大模型智能体应用,附有图文+示例代码】

文章目录 一.Spring Ai介绍1.0 认识Spring Ai1.1 特征1.1 大模型专业名字介绍1.1.1 RAG(检索增强生成)RAG 的基本原理RAG 的关键技术RAG 的优势RAG 的应用场景 1.1.2 fine-tuning(微调)1.1.3 function-call(函数调用) 1.2 创建简单的Spring Ai项目 二.Spring Ai简单的智能应用2…

51c自动驾驶~合集53

我自己的原文哦~ https://blog.51cto.com/whaosoft/13431196 #DriveTransformer 上交提出&#xff1a;以Decoder为核心的大一统架构写在前面 & 笔者的个人理解 当前端到端自动驾驶架构的串行设计导致训练稳定性问题&#xff0c;而且高度依赖于BEV&#xff0c;严重限…

【C语言】联合体 `union` 的妙用

C 语言联合体的妙用:结合 . 和 -> 操作符与 typedef 的深入剖析 在 C 语言中,联合体(union)是一种独特的复合数据类型,因其内存共享特性而在内存优化、类型切换和底层操作中展现出妙用。与结构体(struct)不同,联合体允许同一块内存存储不同类型的数据,提供高效且灵…

UDP协议(20250303)

1. UDP UDP:用户数据报协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;传输层协议之一&#xff08;UDP&#xff0c;TCP&#xff09; 2. 特性 发送数据时不需要建立链接&#xff0c;节省资源开销不安全不可靠的协议 //一般用在实时性比较高…

自动化学习-使用git进行版本管理

目录 一、为什么要学习git 二、git是什么 三、git如何使用 1、git的下载安装和配置 2、git常用的命令 3、gitee远程仓库的使用 &#xff08;1&#xff09;注册 &#xff08;2&#xff09;创建仓库 &#xff08;3&#xff09;配置公钥&#xff08;建立电脑和git…

20250301在chrome中安装CRX猫抓

20250301在chrome中安装CRX猫抓 2025/3/1 18:08 百度&#xff1a;猫抓 CRX https://www.crx4chrome.com/crx/49597/ 猫抓 (cat-catch) Crx File 2.5.9 for Chrome (Latest Version) Get Latest Version of 猫抓 (cat-catch) from Web Store Developer Tools > cat-catch / E…

[LeetCode]day33 150.逆波兰式求表达值 + 239.滑动窗口最大值

逆波兰式求表达值 题目链接 题目描述 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。 每个操作数&#xff08;运…

pnpm+monorepo实现前端公共函数、组件库

一、前言 1. pnpm pnpm 是前端包管理工具之一&#xff0c;常见的还有npm、yarn等&#xff0c;但pnpm由于安装速度快、磁盘占用低、内置支持monorepo等优势&#xff0c;所以更推荐使用。 1-1 包管理工具核心特点对比 特性pnpmnpmyarn安装速度&#x1f680; 快&#xff08;基…

【计算机网络入门】初学计算机网络(八)

目录 1. S-W协议的信道利用率 2. GBN、SR协议的信道利用率 3.术语补充 3.1 滑动窗口协议 3.2 ARQ协议、连续ARQ协议 4. 信道划分介质访问控制 4.1 时分复用&#xff08;TDM&#xff09; 4.2 统计时分复用&#xff08;STDM&#xff09; 4.3 频分复用&#xff08;FDM&a…

JVM基本概念及内存管理模型

一、JVM基本概念 JVM&#xff08;Java Virtual Machine&#xff0c;Java 虚拟机&#xff09;是 Java 程序运行的核心组件。它负责将 Java 字节码转换为特定平台的机器指令&#xff0c;并提供内存管理、垃圾回收、安全性等功能。JVM 的主要功能包括以下&#xff1a; 加载和执行…

Docker 学习(三)——数据管理、端口映射、容器互联

一、数据管理 容器中的管理数据主要有两种方式&#xff1a; 数据卷 &#xff08;Data Volumes&#xff09;&#xff1a; 容器内数据直接映射到本地主机环境&#xff1b; 数据 卷容器&#xff08; Data Volume Containers&#xff09;&#xff1a; 使用特定容器维护数据卷 1.…

解锁Egg.js:从Node.js小白到Web开发高手的进阶之路

一、Egg.js 是什么 在当今的 Web 开发领域&#xff0c;Node.js 凭借其事件驱动、非阻塞 I/O 的模型&#xff0c;在构建高性能、可扩展的网络应用方面展现出独特的优势 &#xff0c;受到了广大开发者的青睐。它让 JavaScript 不仅局限于前端&#xff0c;还能在服务器端大展身手&…

我的ChatGPT怎么登不上?

近期&#xff0c;不少用户反馈在使用ChatGPT时遇到登录困难、连接超时等问题。本文将从技术角度分析常见原因&#xff0c;并提供合规、安全的解决方案&#xff0c;同时结合开发者实际需求推荐实用工具&#xff0c;助您高效应对登录障碍。 ChatGPT登录失败的常见原因 网络环境限…

小米手机如何录制屏幕?手机、电脑屏幕录制方法分享

大家最近有没有遇到想记录手机屏幕操作的情况&#xff1f; 比如精彩的游戏瞬间、有趣的视频教程&#xff0c;或者需要录制屏幕来制作演示材料。小米手机在这方面可是个好帮手&#xff0c;今天就来给你好好唠唠&#xff0c;小米手机如何录制屏幕&#xff0c;以及后续如何处理这…