KeepAlive与RouterView缓存

参考

vue动态组件<Component>与<KeepAlive>

KeepAlive官网介绍

缓存之keep-alive的理解和应用

Vue3+Vite KeepAlive页面缓存问题

vue多级菜单(路由)导致缓存(keep-alive)失效

vue3 router-view keeperalive对于同一路径但路径参数不同

文章目录

效果

main.js

js 复制代码
import { createApp } from 'vue'

import './style.css'

import App from './App.vue'
import router from './router'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(router)
app.use(ElementPlus)
app.mount('#app')

router.js

js 复制代码
import { createWebHistory, createRouter } from "vue-router"

import Home from '@/views/Home.vue'
import Chat from '@/views/Chat.vue'
import ChatDetail from '@/views/ChatDetail.vue'

const routes = [
    {
        path: '/',
        redirect: '/home'
    },
    {
        path: '/home',
        name: 'home',
        component: Home
    },
    {
        path: '/chat',
        name: 'chat',
        component: Chat,
        children: [
            {
                path: 'detail/:id',
                name: 'chatDetail',
                component: ChatDetail
            },
        ]
    },
]
const router = createRouter({
    history: createWebHistory(),
    routes,
})

export default router

App.vue

html 复制代码
<template>
  <div style="height: 100%;">

    <div class="header">
      <el-button @click="nav('/home')">/home</el-button>
      <el-button @click="nav('/chat')">/chat</el-button>
      <el-button @click="nav('/chat/detail/1')">/chat/detail/1</el-button>
      <el-button @click="nav('/chat/detail/2')">/chat/detail/2</el-button>

      <div style="height:100%;width:1px;background-color:#eee;margin: 10px;"></div>

      <!-- 这里的缓存的意思是: 当从ChatDetail组件切到Home组件时, Chat组件实例里的数据还是否缓存 -->
      <el-button @click="cachedComponents = ['Chat']">缓存chat</el-button>
      <el-button @click="cachedComponents = []">取消缓存chat</el-button>{{cachedComponents}}
    </div>

    <!-- 当在home组件与chat组件切换时, 被切走的组件会被销毁, 切过去的组件会被创建 -->
    <!-- <router-view class="container-wrapper"/> -->

    <!-- home组件和chat组件都仅仅被创建了1次, 当在home组件与chat组件切换时, home组件与chat组件并未被销毁或创建 -->
    <!-- <router-view v-slot="{ Component }">
        <keep-alive>
          <component :is="Component" class="container-wrapper"/>
        </keep-alive>
    </router-view> -->

    <!-- home组件仅被创建了1次并且切走时会被缓存下来不会被销毁, 切过来时不会重新创建; 
         而chat组件被切走会被销毁, 切到chat组件时, chat组件会被创建;
         这里的include指的是 组件名称, 而不是路由名称 -->
    <!-- <router-view v-slot="{ Component }">
        <keep-alive :include="['Home']">
          <component :is="Component" class="container-wrapper"/>
        </keep-alive>
    </router-view> -->

    <router-view v-slot="{ Component }">
        <keep-alive :include="cachedComponents">
          <component :is="Component" class="container-wrapper"/>
        </keep-alive>
    </router-view>

  </div>
</template>

<script setup>
  import {ref} from 'vue'
  import { useRouter, useRoute } from 'vue-router';

  const router = useRouter();
  const route = useRoute();

  const cachedComponents = ref([])

  function nav(path) {
      // console.log(path);
      router.push(path);
  }
</script>

<style>
body,html {
  margin:0;
  padding: 0;
  height: 100%;
}
#app {
  height: 100%;
  & .header {
    height: 51px;
    line-height: 51px;
    padding: 0 20px;
    border-bottom: 1px solid #eee;
    display: flex;
    align-items: center;
    justify-content: flex-start;
  }
  & .container-wrapper {
    height: calc(100% - 52px);
  }
}
</style>

Home.vue

html 复制代码
<template>
    <div class="home">
        <div>
            <h1>home</h1>
        </div>
    </div>
</template>

<script setup>
import {ref, onActivated, onDeactivated ,onUnmounted} from 'vue'

    import {useRouter} from 'vue-router';
    // 获取路由器
    const router = useRouter()
    
    console.log('【Home组件】创建');
    
    onUnmounted(()=>{
        console.log('【Home组件】销毁');
    })

</script>

<style lang="scss">
.home {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
</style>

Chat.vue

html 复制代码
<template>
    <div class="container">
        <div class="left">
            <el-button @click="nav('/home')">/home</el-button>
            <el-button @click="nav('/chat/detail/1')">/chat/1</el-button>
            <el-button @click="nav('/chat/detail/2')">/chat/2</el-button>
        </div>
        <div class="right">

            <!-- <router-view/> -->

            <!-- <router-view v-slot="{ Component }">
                <keep-alive>
                    <component :is="Component"/>
                </keep-alive>
            </router-view> -->

            <!-- 这里给component添加1个key之后, 就可以根据路由路径来缓存组件实例了: 1个路由路径对应1个组件实例 -->
            <router-view v-slot="{ Component }">
                <keep-alive>
                    <component :is="Component" :key="route.path"/>
                </keep-alive>
            </router-view>
        </div>
    </div>
</template>

<script setup>
    import { onUnmounted } from 'vue'
    import { useRouter,useRoute } from 'vue-router'
    const route = useRoute()
    const router = useRouter();
    function nav(path) {
        // console.log(path);
        router.push(path);
    }

    console.log('【Chat组件】创建');
    
    onUnmounted(()=>{
        console.log('【Chat组件】销毁');
    })
</script>

<style lang="scss" scoped>
.container {
    display: flex;
    .left {
        width: 220px;
        border-right: 1px solid #eee;
        display: flex;
        flex-direction: column;
        align-items: center;
        padding-top: 10px;
        background-color: #f2f2f2;
        .el-button {
            margin-bottom: 10px;
            width: 80%;
        }
    }
    .right {
        flex: 1;
        padding: 20px;
        background-color: #e1e1e1;
    }   
}
.el-button+.el-button {
    margin-left: 0;
}
</style>
ChatDetail.vue
html 复制代码
<template>
    <div class="chat-box">
        <div class="header">
            <h1>会话{{route.params.id}}</h1>
        </div>
        <div class="msg-list">
            <el-input v-model="content" placeholder="请输入"></el-input>
        </div>
    </div>
</template>

<script setup>
import {ref, onActivated, onDeactivated ,onUnmounted} from 'vue'
import {useRoute} from 'vue-router';
const content = ref();
const route = useRoute();

onActivated(()=>{
    console.log('---【ChatDetail组件】激活---');
});
onDeactivated(()=>{
    console.log('---【ChatDetail组件】取消激活---');
});

console.log('---【ChatDetail组件】创建---');

onUnmounted(()=>{
    console.log('---【ChatDetail组件】销毁---');
})

</script>

<style lang="scss" scoped>
    .chat-box {
        display: flex;
        flex-direction: column;
        height: 100%;
        .msg-list {
            flex: 1;
        }
    }
    .header {
        border: 2px solid #eee;
        line-height: 68px;
        height: 68px;
        h1 {
            margin: 0;
        }
    }
</style>
相关推荐
晴空对晚照4 小时前
[动手学习深度学习]26. 网络中的网络 NiN
网络·深度学习·学习
gzgenius5 小时前
独立部署DeepSeek 大语言模型(如 DeepSeek Coder、DeepSeek LLM)可以采用什么框架?
人工智能·学习·架构·deepseek
charlie1145141918 小时前
单片机开发资源分析的实战——以STM32F103C8T6为例子的单片机资源分析
stm32·单片机·嵌入式硬件·学习·教程
努力往上爬de蜗牛9 小时前
react学习1.搭建react环境
javascript·学习·react.js
sealaugh329 小时前
aws(学习笔记第三十三课) 深入使用cdk 练习aws athena
笔记·学习·aws
Liii4039 小时前
Java学习——数据库查询操作
java·数据库·学习
TO_WebNow10 小时前
Python学习- 数据结构类型
开发语言·python·学习
怪我冷i10 小时前
LogicFlow介绍
人工智能·学习·大模型
Suckerbin10 小时前
PHP前置知识-HTML学习
前端·学习·html