主页 > 开源代码  > 

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

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

目录 前言1. 基本知识2. Demo2.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>

运行效果:

组件首次渲染时,created() 会触发当组件切换回来时,activated() 会触发,而不会重新执行 created()切换到别的组件时,deactivated() 触发,而不会执行 destroyed()只有当缓存被清除时,才会执行 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>

动态路由的常用操作

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

动态移除路由:router.removeRoute('NewPage')

监听路由变化

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' }) 对应一致

标签:

详细分析KeepAlive的基本知识并缓存路由(附Demo)由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“详细分析KeepAlive的基本知识并缓存路由(附Demo)