Vue3嵌套路由中使用keep-alive緩存多層的實(shí)現(xiàn)
前言
keep-alive是Vue中的緩存標(biāo)簽, 組件在標(biāo)簽中的內(nèi)容會(huì)被緩存下來;但是在多層嵌套的router-view中, 只能緩存到該層下的router-view, 由于路由嵌套比較常見,所以這里提供兩種我覺得OK的解決方案。
解決思路
- 路由層級扁平化,在路由守衛(wèi)中執(zhí)行一個(gè)拍平的函數(shù),將需要緩存的路由提升到第一層,這樣處理會(huì)影響到路由層級,最直白的影響如對 面包屑 等功能有直接影響
- 把所有的
router-view都通過keep-alive包裹起來, 通過keep-alive的include,exclude來判斷是否需要緩存。
Demo項(xiàng)目結(jié)構(gòu)
router.ts

路由的結(jié)構(gòu)大概是這樣的 Layout > TableManage > (List, Detail, Add...)
路由層級扁平化
在路由的 afterEach 執(zhí)行一個(gè)扁平化方法, 舉例:
import router from '@/router/index'
import PageTitleUtils from '@/utils/PageTitleUtils'
import { ElMessage } from 'element-plus'
import useStore from '@/store/index'
import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const { user, routeStore } = useStore()
const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
NProgress.start()
if (user.hasToken()) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (user.hasUserInfo()) {
next()
NProgress.done()
} else {
try {
await user.getUserInfo()
await routeStore.setRoutes()
next({ ...to, replace: true })
NProgress.done()
} catch (error: any) {
routeStore.resetRoutes()
user.resetUserInfo()
ElMessage.error(error || 'Has Error')
next(`/login?redirect=${to.fullPath}`)
NProgress.done()
}
}
}
} else {
/* has no token */
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
NProgress.done()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.fullPath}`)
NProgress.done()
}
}
})
router.afterEach((to: any) => {
NProgress.done()
// set page title
const { meta }: any = to
document.title = PageTitleUtils.getPageTitle(meta.title)
// delayering router
delayeringRoute(to)
})
/**
* 遞歸處理多余的 layout : <router-view>,
* 讓需要訪問的組件保持在第一層 index : <router-view> 之下
*/
function delayeringRoute(to: RouteLocationNormalized) {
if (to.matched && to.matched.length > 2) {
for (let i = 0; i < to.matched.length; i++) {
const element = to.matched[i]
// 移除多余的 layout, 也許你項(xiàng)目中并不叫 layout ,自行修改此處
if (element.components?.default.name === 'layout') {
to.matched.splice(i, 1)
handleKeepAlive(to)
}
}
}
}以上代碼示例中, delayeringRoute 是移除多余 layout 的方法, 在路由的afterEach方法中去移除,弊端很明顯, 路由的結(jié)構(gòu)受到了影響
給所有的 router-view 都嵌套上 keep-alive
這是我比較推薦的一種方法, 沒什么副作用,也不麻煩, 畢竟所有的 router-view 都一樣,如果你使用的IDE是vscode,可以直接把這段代碼寫進(jìn)項(xiàng)目中的代碼片段, 方便使用。
Layout的Main
<script lang="ts" setup name="AppMain">
import { useRoute } from 'vue-router'
import useStore from '@/store';
import { storeToRefs } from 'pinia';
const route = useRoute()
const { tagview } = useStore()
const { cacheList } = storeToRefs(tagview)
</script>
<template>
<div class="app-main">
<router-view v-slot="{ Component }">
<keep-alive :include="cacheList">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</router-view>
</div>
</template>
<style scoped lang="scss">
</style>其他嵌套的路由, 不管幾層,都可以這樣處理
<script lang="ts" setup name="TableManage">
import { useRoute } from 'vue-router'
import useStore from '@/store';
import { storeToRefs } from 'pinia';
import { onMounted } from 'vue';
const route = useRoute()
const { tagview } = useStore()
const { cacheList } = storeToRefs(tagview)
onMounted(() => {
tagview.addCacheList('TableManage')
})
</script>
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="cacheList">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</router-view>
</template>這樣就可以實(shí)現(xiàn)嵌套路由的緩存了。 附上演示

到此這篇關(guān)于Vue3嵌套路由中使用keep-alive緩存多層的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Vue3 keep-alive緩存多層內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue中Keep-Alive緩存組件使用語法及原理深度解析
- Vue3除了keep-alive還有哪些實(shí)現(xiàn)頁面緩存詳解
- React實(shí)現(xiàn)頁面狀態(tài)緩存(keep-alive)的示例代碼
- Vue路由組件的緩存keep-alive和include屬性的具體使用
- Vue keep-alive組件的使用及如何清除緩存
- vue3?keep-alive實(shí)現(xiàn)tab頁面緩存功能
- vue使用keep-alive進(jìn)行組件緩存方法詳解(組件不緩存問題解決)
- vue中keep-alive組件實(shí)現(xiàn)多級嵌套路由的緩存
- 快速解決 keep-alive 緩存組件中定時(shí)器干擾問題
相關(guān)文章
在vue中更換字體,本地存儲(chǔ)字體非引用在線字體庫的方法
今天小編就為大家分享一篇在vue中更換字體,本地存儲(chǔ)字體非引用在線字體庫的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
vue-cli打包后本地運(yùn)行dist文件中的index.html操作
這篇文章主要介紹了vue-cli打包后本地運(yùn)行dist文件中的index.html操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
vue?codemirror實(shí)現(xiàn)在線代碼編譯器效果
這篇文章主要介紹了vue-codemirror實(shí)現(xiàn)在線代碼編譯器?,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
Vue生命周期和鉤子函數(shù)的詳解與經(jīng)典面試題
Vue生命周期是指vue實(shí)例對象從創(chuàng)建之初到銷毀的過程,vue所有功能的實(shí)現(xiàn)都是圍繞其生命周期進(jìn)行的,下面這篇文章主要給大家介紹了關(guān)于Vue生命周期和鉤子函數(shù)的相關(guān)資料,需要的朋友可以參考下2021-10-10
Vue中設(shè)置el-select的高度不生效問題及解決方案
文章介紹了如何使用ElementUI框架中的el-select組件,并解決設(shè)置其高度不生效的問題,在Vue2.x中,使用/deep/關(guān)鍵字可以穿透組件作用域修改樣式;在Vue2.6+到Vue3初期,推薦使用::v-deep關(guān)鍵字;在最新的Vue3和構(gòu)建工具中,推薦使用:deep()偽類來代替::v-deep2025-01-01

