当前位置: 首页 > 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 = 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' }) 对应一致


http://www.kler.cn/a/572019.html

相关文章:

  • JavaWeb基础专项复习6(2)——AJAX补充
  • [leetcode]704.二分查找-简单
  • 【Canny 边缘检测详细讲解】
  • 【ORACLE】ORACLE19C在19.13版本前的一个严重BUG-24761824
  • 统计URL出现层级及次数
  • 2025-03-04 学习记录--C/C++-C语言 判断是否是素数
  • C# .NETCore ZipArchive 处理大容量文件导致内存占用高的问题
  • 【YOLO12全网首发】训练+测试行人摔倒
  • json介绍、python数据和json数据的相互转换
  • 华为 VRP 系统简介配置SSH,TELNET远程登录
  • Kubernetes Pod 管理及优化
  • 利用出书策略结合定制开发开源AI智能名片S2B2C商城小程序获取私域流量的探索
  • vue实例
  • 通配符匹配在Redis中的实现
  • AI绘画软件Stable Diffusion详解教程(6):文生图、提示词细说与绘图案例
  • [Web 安全] PHP 反序列化漏洞 —— PHP 魔术方法
  • CSS Overflow 属性详解
  • 千里科技亮相吉利AI智能科技发布会,共启“AI+车”新纪元
  • Asp.Net Core WebAPI开发教程(入门)
  • 机器人训练环境isaac gym以及legged_gym项目的配置问题