對于vue的 keep-alive 組件,先簡單介紹一下:
<keep-alive> 包裹動態(tài)組件時,會緩存不活動的組件實(shí)例,而不是銷毀它們。和 <transition> 相似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數(shù)將會被對應(yīng)執(zhí)行。
include 和 exclude 屬性允許組件有條件地緩存。二者都可以用逗號分隔字符串、正則表達(dá)式或一個數(shù)組來表示:
<!-- 逗號分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正則表達(dá)式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- Array (use `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
匹配首先檢查組件自身的 name 選項,如果 name 選項不可用,則匹配它的局部注冊名稱(父組件 components 選項的鍵值。
在項目中,有些頁面需要緩存,有些不需要,這就需要使用keep-alive進(jìn)行相關(guān)控制,來達(dá)到效果。 一般的使用方法,可能都是下面的這種:
先在路由中配置meta: { keepAlive: true },然后
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
根據(jù)keepAlive的值來進(jìn)行是否緩存判斷。
這種對于常規(guī)的頁面緩存是有效的。 但是在項目中,一個頁面不會一直被緩存的,有時需要重新渲染。比如,一個列表頁(a)、詳情頁(b)和詳情擴(kuò)展頁(c),a -> b頁面,a是緩存頁,b需要在每次打開時,重新渲染;b -> c頁面,此時b需要被緩存,從c返回時,需要b保持不變。 對于這種需求,目前大部分的解決方案是:通過在路由導(dǎo)航守衛(wèi)中判斷b頁面如果是前往c頁面,則需要緩存,如果前往a頁面,則b不需要緩存。
beforeRouteLeave(to, from, next) {
if(to.path.includes('c')) {
from.meta.keepAlive = true;
} else {
from.meta.keepAlive = false;
}
next();
}
這種方式會出現(xiàn)一個問題: 首先,(具體例子,從上到下對于a、b、c),第一次前往c頁面時,b確實(shí)會被緩存,

但是我們返回a頁面,再前往b頁面時,會出現(xiàn)一個新的b緩存頁,

就算這不影響我們的性能,但是你繼續(xù)前往c頁面時,

我們之前的b被直接銷毀,導(dǎo)致返回b頁面時,會返回到第一次緩存的頁面,而且之后一直都是只回到第一次的頁面,

這并不是我們想要看到的。 網(wǎng)上搜羅一番,有說可以在回到a頁面時,把緩存的b頁面手動銷毀,vue提供一個vm.$destroy()的方法,但是這是不被推薦使用的,我們先試一下:
beforeRouteLeave(to, from, next) {
if(to.path.includes('c')) {
from.meta.keepAlive = true;
} else {
from.meta.keepAlive = false;
this.$destroy();
}
next();
}
繼續(xù)重復(fù)一下上面的操作,發(fā)現(xiàn)第一次的頁面會被緩存,

第二次從a前往b,在前往c之后,b一直會被銷毀,無法緩存,有時還會出現(xiàn)沒有銷毀的情況,導(dǎo)致第一次的緩存一直存在,之后每次還是會銷毀b,

[圖片上傳中...(image-ac4689-1600762988122-1)]
全都不是我們的菜~!! 通過翻讀vue文檔中的keep-alive的介紹,注意到了它的一個屬性:include,那就換一種寫法,在App.vue中,通過監(jiān)聽路由是否是b到a頁面,來判斷要不要緩存:
<keep-alive :include="keepAlive">
<router-view></router-view>
</keep-alive>
export default {
name: "App",
data() {
return {
keepAlive: ['a', 'b']
}
},
watch: {
$route(to, from) {
// 如果是從b到a頁面,則不緩存b
if(from.name === 'b' && to.name === 'a') {
this.keepAlive = ['a']
} else {
this.keepAlive = ['a', 'b']
}
}
}
};
大功告成
