Vue Router路由動(dòng)態(tài)緩存組件使用詳解
一、簡(jiǎn)介
Vue Router 允許你緩存路由組件,這樣在用戶(hù)導(dǎo)航回之前的頁(yè)面時(shí),組件的狀態(tài)會(huì)被保留而不是重新渲染。這可以通過(guò)使用 <keep-alive>
組件來(lái)實(shí)現(xiàn)。
<keep-alive>
是一個(gè)內(nèi)置抽象組件,它自身不會(huì)渲染一個(gè) DOM 元素,也不會(huì)出現(xiàn)在父組件鏈中。
它的主要作用是緩存不活動(dòng)的組件實(shí)例,而不是銷(xiāo)毀它們。
當(dāng)組件在 <keep-alive>
包裹下被切換時(shí),它的狀態(tài)(包括數(shù)據(jù)、DOM 結(jié)構(gòu)等)都會(huì)被保留,以便在下次重新顯示時(shí)能夠恢復(fù)之前的狀態(tài),而不是重新創(chuàng)建組件實(shí)例。
基本用法
<keep-alive> <component :is="currentTabComponent"></component> </keep-alive>
在上面的例子中,currentTabComponent
是一個(gè)動(dòng)態(tài)組件,它的值會(huì)根據(jù)當(dāng)前選中的標(biāo)簽頁(yè)而變化。
使用 <keep-alive>
后,當(dāng)切換標(biāo)簽頁(yè)時(shí),之前的組件實(shí)例會(huì)被緩存起來(lái),而不是被銷(xiāo)毀。
生命周期鉤子
被 <keep-alive>
包裹的組件擁有兩個(gè)特有的生命周期鉤子:activated
和 deactivated
。
activated
:當(dāng)組件被激活時(shí)調(diào)用,即在 keep-alive 緩存中組件再次可見(jiàn)時(shí)被調(diào)用。deactivated
:當(dāng)組件被停用時(shí)調(diào)用,即在 keep-alive 緩存中組件不可見(jiàn)時(shí)被調(diào)用。
這兩個(gè)鉤子可以幫助你更好地管理組件的狀態(tài),比如當(dāng)組件重新被激活時(shí),你可能需要重新獲取數(shù)據(jù)或者更新視圖。
二、定義是否緩存組件
根據(jù)路由的 meta
字段中的 keepAlive
屬性來(lái)決定是否緩存組件。
如果 keepAlive 為 true,則組件會(huì)被緩存;否則,它會(huì)被緩存。
const routes = [ { path: '/foo', component: Foo, meta: { keepAlive: true } // 這個(gè)組件會(huì)被緩存 }, { path: '/bar', component: Bar, meta: { keepAlive: false } // 沒(méi)有設(shè)置 meta.keepAlive 或其值為 false,則組件不會(huì)被緩存 } // ... 其他路由配置 ];
三、緩存組件
1. 通過(guò) :include 屬性實(shí)現(xiàn)
可利用keep-alive
的 include
或 exclude
屬性(include 和 exclude 包含的name 是組件的name不是router name)來(lái)設(shè)置緩存:
include
值為字符串或者正則表達(dá)式匹配的組件name會(huì)被緩存。exclude
值為字符串或正則表達(dá)式匹配的組件name不會(huì)被緩存。
vue2.x中
通過(guò) <keep-alive>
的 :include
屬性來(lái)實(shí)現(xiàn)動(dòng)態(tài)緩存組件
<template> <div id="app"> <keep-alive :include="cachedViews"> <router-view></router-view> </keep-alive> </div> </template> <script> export default { name: 'App', data() { return { cachedViews: [] // 存儲(chǔ)需要緩存的組件名 }; }, watch: { $route(to, from) { // 過(guò)濾出需要緩存的組件,即 meta.keepAlive = true 的組件 const keepAliveComponent = to.matched.filter(record => { return record.meta && record.meta.keepAlive; }); if (keepAliveComponent.length) { // 把需要緩存的組件的name放到cachedViews集合里 this.cachedViews = this.cachedViews.concat(keepAliveComponent.map(record => record.name)); } else { const index = this.cachedViews.indexOf(to.name); if (index > -1) { this.cachedViews.splice(index, 1); } } } } }; </script>
vue3.x中
在 Vue 3 中同樣可以使用 <keep-alive>
的 :include
屬性來(lái)實(shí)現(xiàn)動(dòng)態(tài)緩存組件:
<template> <div id="app"> <keep-alive :include="cachedViews"> <router-view></router-view> </keep-alive> </div> </template> <script> import { ref, onMounted, watch, onUnmounted } from 'vue'; import { useRoute } from 'vue-router'; export default { name: 'App', setup() { const cachedViews = ref([]); const route = useRoute(); const updateCachedViews = () => { const keepAliveComponent = route.matched.filter(record => { return record.meta && record.meta.keepAlive; }); cachedViews.value = keepAliveComponent.map(record => record.name); }; onMounted(() => { updateCachedViews(); }); watch( route, () => { updateCachedViews(); }, { immediate: false } ); onUnmounted(() => { // 清理操作,如果需要的話(huà) }); return { cachedViews }; } }; </script>
2. 通過(guò) v-slot 功能實(shí)現(xiàn)
由于Vue 3 由于引入了組合式 API
和 v-slot
功能,有更簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)動(dòng)態(tài)緩存:
<template> <div id="app"> <router-view v-slot="{ Component }"> <keep-alive v-if="$route.meta && $route.meta.keepAlive"> <component :is="Component" /> </keep-alive> <component v-else :is="Component" /> </router-view> </div> </template> <script> import { defineComponent } from 'vue'; export default defineComponent({ name: 'App' }); </script>
使用<router-view>
的 v-slot
功能來(lái)訪(fǎng)問(wèn)當(dāng)前路由組件的實(shí)例。
然后,我們檢查這個(gè)組件的 meta.keepAlive
屬性來(lái)決定是否將其包裹在 <keep-alive>
中。
3. 通過(guò) v-if 來(lái)實(shí)現(xiàn)
在Vue2和Vue3中都可以使用 v-if="$route.meta.keepAlive"
來(lái)判斷哪些組件需要緩存,簡(jiǎn)單粗暴
<template> <div id="app"> <keep-alive v-if="$route.meta.keepAlive"> <router-view></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view> </div> </template> <script> import { defineComponent } from 'vue'; export default defineComponent({ name: 'App' }); </script>
四、注意事項(xiàng)
- 雖然
<keep-alive>
可以提高性能,但也要避免過(guò)度使用,因?yàn)榫彺娴慕M件實(shí)例會(huì)占用內(nèi)存。 - 當(dāng)組件被
<keep-alive>
包裹時(shí),它的created
和mounted
鉤子只會(huì)在第一次渲染時(shí)調(diào)用,之后的切換不會(huì)再次觸發(fā)這兩個(gè)鉤子。 - 如果需要強(qiáng)制刷新緩存的組件,可以通過(guò)改變 key 屬性或者使用 ·include/exclude· 屬性來(lái)動(dòng)態(tài)控制哪些組件需要被緩存。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue.js路由實(shí)現(xiàn)選項(xiàng)卡簡(jiǎn)單實(shí)例
這篇文章主要為大家詳細(xì)介紹了Vue.js路由實(shí)現(xiàn)選項(xiàng)卡簡(jiǎn)單實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Vue?Router嵌套路由(children)的用法小結(jié)
嵌套路由就是父路由里面嵌套他的子路由,父路由有自己的路由導(dǎo)航和路由容器(router-link、router-view),通過(guò)配置children可實(shí)現(xiàn)多層嵌套,這篇文章主要介紹了Vue--Router--嵌套路由(children)的用法,需要的朋友可以參考下2022-08-08使用Vue創(chuàng)建前后端分離項(xiàng)目的完整過(guò)程(前端部分)
這篇文章主要介紹了使用Vue.js和Node.js搭建一個(gè)前端和后端分離的項(xiàng)目,并使用VueCLI3腳手架、axios進(jìn)行HTTP請(qǐng)求、Vue-router實(shí)現(xiàn)前端路由和vuex進(jìn)行狀態(tài)管理,需要的朋友可以參考下2025-01-01vue 解除鼠標(biāo)的監(jiān)聽(tīng)事件的方法
這篇文章主要介紹了vue 解除鼠標(biāo)的監(jiān)聽(tīng)事件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

基于element-ui表格的二次封裝實(shí)現(xiàn)

vue不通過(guò)路由直接獲取url中參數(shù)的方法示例