完整項(xiàng)目地址:vue3-element-plus
體驗(yàn)地址:http://8.135.1.141/vue3-admin-plus
系列文章入口:
前言
當(dāng)我們?cè)谀承┨囟▓鼍爸行枰彺婺硞€(gè)頁面屯伞,此時(shí)就需要用到我們所需要講的keep-alive菠红,本篇主要講解架構(gòu)中keep-alive的原理和使用
架構(gòu)keep-alive核心源碼分析
src/layout/components/AppMain.vue
<transition v-if="settings.mainNeedAnimation" mode="out-in" name="fade-transform">
<!-通過keep-alive的include屬性,根據(jù)組件的name進(jìn)行緩存块差,如KeepAlive ->
<keep-alive :include="cachedViews">
<component :is="Component" :key="key" />
</keep-alive>
</transition>
<script>
//通過vuex里的cachedViews控制需要緩存的頁面
//cachedViews: Array<string>
const cachedViews = computed(() => {
return store.state.app.cachedViews
})
// cachePage: true ->頁面初始化后緩存本頁面
// leaveRmCachePage: true -> 頁面離開后或者關(guān)閉后, 移除本頁面緩存
// leaveRmCachePage和cachePage來自于router里的配置倔丈,請(qǐng)看下面介紹
let oldRoute = null
//代碼原理:通過計(jì)算屬性監(jiān)聽憨闰,當(dāng)router.path變化是觸發(fā)get函數(shù)調(diào)用。從而獲取當(dāng)前路由需五,根據(jù)路由配置信息里的cachePage和leaveRmCachePage決定是否需要緩存和移除緩存
const key = computed({
get() {
//頁面離開時(shí)鹉动,如果有cachePage=true和leaveRmCachePage=true,則移除緩存
if (oldRoute?.name) {
if (oldRoute.meta?.leaveRmCachePage && oldRoute.meta?.cachePage) {
store.commit('app/M_DEL_CACHED_VIEW', oldRoute.name)
}
}
//頁面進(jìn)入時(shí)如果有cachePage=true宏邮,則設(shè)置緩存
if (route.name) {
if (route.meta?.cachePage) {
store.commit('app/M_ADD_CACHED_VIEW', route.name)
}
}
//保存上一個(gè)路由信息(也就是當(dāng)前頁面的路由信息)
oldRoute = JSON.parse(JSON.stringify({ name: route.name, meta: route.meta }))
return route.path
}
})
</script>
如何使用
src/router/index.js
{
path: 'keep-alive',
component: () => import('@/views/example/keep-alive'),
name: 'KeepAlive',
//如果配置了cachePage: true 則當(dāng)前頁面進(jìn)入后泽示,進(jìn)行緩存。 默認(rèn)是false
//若果配置了leaveRmCachePage:true 則當(dāng)前頁離開后蜀铲,頁面會(huì)被移除緩存边琉。默認(rèn)是false
meta: { title: 'Keep-Alive', cachePage: true, leaveRmCachePage: false }
},
{
path: 'router-demo-f',
name: 'routerDemoF',
hidden: true,
component: () => import('@/views/example/keep-alive/RouterDemoF.vue'),
meta: { title: 'RouterDemo-F', cachePage: true, activeMenu: '/writing-demo/keep-alive' }
},
{
path: 'router-demo-s',
name: 'routerDemoS',
hidden: true,
component: () => import('@/views/example/keep-alive/RouterDemoS.vue'),
meta: { title: 'RouterDemo-S', cachePage: true, activeMenu: '/writing-demo/keep-alive' }
}
在meta里設(shè)置cachePage或者leaveRmCachePage,決定是否需要緩存和移除緩存
各種組合情況
cachePage: true, leaveRmCachePage: true ->頁面進(jìn)入時(shí)緩存记劝,離開時(shí)移除緩存
cachePage: false 或者不寫 ->頁面不緩存变姨,按正常的頁面走
cachePage: true, leaveRmCachePage: false -> 頁面進(jìn)入時(shí)緩存,離開時(shí)不移除緩存厌丑。那么此頁面緩存會(huì)一直存在定欧,除非手動(dòng)移除
如果進(jìn)行多級(jí)緩存呢
有時(shí)我們會(huì)有這種業(yè)務(wù)場景
從A頁面跳到B頁面在到C頁面,此時(shí)需要A,B,C頁面都需要緩存怒竿。保存A,B,C頁面的狀態(tài)砍鸠,如A頁面的列表搜索條件等。但是如果跳出A,B,C頁面時(shí)需要同時(shí)清空A,B,C頁面的緩存耕驰,如:
實(shí)現(xiàn)原理
核心代碼
src/views/example/keep-alive/KeepAlive.vue
const $route = useRoute()
const $store = useStore()
// cacheGroup為緩存分組 KeepAlive->routerDemoF->routerDemoS
let cacheGroup = ['KeepAlive', 'routerDemoF', 'routerDemoS']
const unWatch = watch(
() => $route.name,
() => {
//如果進(jìn)入的頁面路由name沒有在cacheGroup中爷辱,則清空這個(gè)cacheGroup配置的頁面緩存
if (!cacheGroup.includes($route.name)) {
//sleep(300) -> 等進(jìn)入其他頁面后在進(jìn)行頁面緩存清空, 用于頁面性能優(yōu)化
useCommon()
.sleep(300)
.then(() => {
//遍歷cacheGroup清空頁面緩存
cacheGroup.forEach((fItem) => $store.commit('app/M_DEL_CACHED_VIEW', fItem))
})
//remove watch
unWatch()
}
},
//deep: true
//immediate進(jìn)入頁面立即監(jiān)聽
{ immediate: true }
)
注:緩存和tab沒有關(guān)聯(lián),和路由配置有關(guān)聯(lián)
架構(gòu)為什么要這樣設(shè)置呢饭弓?
1.緩存和tab沒有關(guān)聯(lián)双饥,更利于緩存的靈活配置。如:當(dāng)我們?cè)趕ettings.js中設(shè)置showTagsView為false時(shí)弟断,依然可以使用路由配置的cachePage或者leaveRmCachePage進(jìn)行設(shè)置緩存咏花,TagsView的顯示和隱藏對(duì)緩存沒有影響。
2.和路由配置有關(guān)聯(lián)阀趴,更利于我們對(duì)緩存的使用昏翰。如,我們可以根據(jù)路由配置的cachePage或者leaveRmCachePage刘急,實(shí)現(xiàn)進(jìn)行頁面是否緩存棚菊,和離開頁面頁面是否移除緩存的組合式選擇。
那么如果我想實(shí)現(xiàn)之前tab打開時(shí)排霉,頁面緩存窍株,tab關(guān)閉時(shí),移除緩存的功能呢攻柠?
在想實(shí)現(xiàn)此功能頁面的路由上設(shè)置
//如果配置了cachePage: true 則當(dāng)前頁面進(jìn)入后球订,進(jìn)行緩存。 默認(rèn)是false
//若果配置了leaveRmCachePage:true 則當(dāng)前頁離開后瑰钮,頁面會(huì)被移除緩存冒滩。默認(rèn)是false
meta: { title: 'Keep-Alive', cachePage: true, leaveRmCachePage: ture }
cachePage: true, leaveRmCachePage: ture -> 進(jìn)入時(shí)緩存,關(guān)閉時(shí)移除緩存