【vue】聊一聊嵌套路由使用keep-alive缓存的实现
 大家应该都写过类似下图布局的页面,一个顶部导航、一个侧边菜单和一个主要内容区域。其中只有主要内容区域是变化。在这个基础上实现缓存大家应该都有经历过。只要在  router-view  上使用  keep-alive  标签就可以轻松实现缓存。但是在多层嵌套的  router-view  中,只能缓存到该层下的  router-view  。针对上面的情况下面聊聊我的实现。(以下内容都是基于Vue3 + pinia 实现)  
 
路由层级扁平化
搜索网上的方案大部分都是说将路由层级扁平化,直白点就是在路由守卫中将route对象的matched属性将使用到router-view的组件进行删除,将路由层级提升,从而实现缓存的目的。这种方案可行,但是不能适用于所有情况。如果路由组件中存在布局(如下图),那该方案会将会丢失这部分(红色框内)内容。 
 所有  router-view  都使用  keep-alive  (推荐) 
 
  既然  keep-alive  无法多层嵌套缓存,那我们可以换个思路,将每个  router-view  都使用  keep-alive  ,通过  include  属性来判断组件是否需要进行缓存。 
 重新封装  router-view  组件 
 
  我们必然不会只在一处使用  router-view  ,那我们就需要对  router-view  组件进行二次封装。举例代码如下 
vue
 <script setup> 
import { computed } from 'vue' 
import { useRouteCacheStore } from '@/stores/modules/route-cache' 
defineProps({ 
 keepalive: { 
 type: Boolean, 
 default: () => false 
 } 
}) 
const routeCacheStore = useRouteCacheStore() 
const keepalives = computed(() => routeCacheStore.keepalives) 
</script> 
<template> 
 <router-view v-slot="{ Component }"> 
 <keep-alive :include="keepalives" v-if="keepalive"> 
 <component :is="Component" /> 
 </keep-alive> 
 <component :is="Component" v-else /> 
 </router-view> 
</template> 
 
  代码中的  keepalives  就是需要缓存组件名称的数组,一般情况下我们都是放在  pinia  或者  vuex  中。 
js
 import { defineStore } from 'pinia' 
export const useRouteCacheStore = defineStore('routeCache', { 
 state: () => ({ 
 keepalives: ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'], 
 }) 
}) 
 
 路由层级
 
 如上图:路由一、二、三为同级路由,其中路由三为使用router-view的组件。路由三下的路由四、五、六也为同级路由,其中路由六为使用router-view的组件。路由六下的路由七、八也为同级路由。嵌套路由层级代码如下
js
 { 
 path: '/route-cache', 
 name: 'routeCache', 
 redirect: { name: 'routeCacheOne' }, 
 component: () => import('../views/route-cache/index.vue'), 
 children: [ 
 { 
 path: '/one', 
 name: 'routeCacheOne', 
 component: () => import('../views/route-cache/views/one/index.vue') 
 }, 
 { 
 path: '/two', 
 name: 'routeCacheTwo', 
 component: () => import('../views/route-cache/views/two/index.vue') 
 }, 
 { 
 path: '/three', 
 name: 'routeCacheThree', 
 redirect: { name: 'routeCacheFour' }, 
 component: () => import('../views/route-cache/views/three/index.vue'), 
 children: [ 
 { 
 path: '/four', 
 name: 'routeCacheFour', 
 component: () => import('../views/route-cache/views/four/index.vue') 
 }, 
 { 
 path: '/five', 
 name: 'routeCacheFive', 
 component: () => import('../views/route-cache/views/five/index.vue') 
 }, 
 { 
 path: '/six', 
 name: 'routeCacheSix', 
 redirect: { name: 'routeCacheSeven' }, 
 component: () => import('../views/route-cache/views/six/index.vue'), 
 children: [ 
 { 
 path: '/seven', 
 name: 'routeCacheSeven', 
 component: () => import('../views/route-cache/views/Seven/index.vue') 
 }, 
 { 
 path: '/eight', 
 name: 'routeCacheEight', 
 component: () => import('../views/route-cache/views/eight/index.vue') 
 }, 
 ] 
 }, 
 ] 
 }, 
 ] 
} 
 
 注意
 如上图的结构,如果所有组件都需要缓存那  keepalives  数组应该等于['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'], 而不是['One', 'Two', 'Four', 'Five', 'Seven', 'Eight']。简单的说就是使用  router-view  的组件(即路由三、路由六)也需要给组件命名并记录到  keepalives  数组中。如果不这么做的话会导致出现部分情况不缓存:  
 
完整演示
 
 
以上就是本次分享的内容,附上 源码 。
感谢看官看到这里,如果觉得文章不错的话,可以给小生的几个开源项目点个Star⭐!
-  
基于 Vue3 + Element-plus 管理后台基础功能框架
-  
预览: https://admin.gumingchen.icu
 -  
Github: https://github.com/gmingchen/agile-admin
 -  
Gitee: https://gitee.com/shychen/agile-admin
 -  
基础版后端: https://github.com/gmingchen/java-spring-boot-admin
 -  
文档: https://admin.gumingchen.icu/doc/
 
 -  
 -  
基于 Vue3 + Element-plus + websocket 即时聊天系统
-  
预览: http://im.gumingchen.icu
 -  
代码: https://github.com/gmingchen/vue3-element-plus-im
 -  
后端代码: https://github.com/gmingchen/java-im
 
 -  
 -  
基于 node 开发的后端服务: https://github.com/gmingchen/node-server
 
 
