在某一些特定場景下,跳轉(zhuǎn)頁面后再返回我們不希望銷毀組件,而是希望頁面緩存下來,保存跳轉(zhuǎn)前的狀態(tài),這時(shí)候就可以用到keep-alive組件。
官方介紹

這個(gè)地方請注意有一個(gè)坑點(diǎn),include 和 exclude 包含的name 是組件的name不是router name.
使用場景
如果未使用keep-alive組件,在路由切換會(huì)對界面進(jìn)行銷毀,在某些業(yè)務(wù)場景下會(huì)使用戶體驗(yàn)不是很友好。
- 主頁面跳轉(zhuǎn)詳情頁再次從詳情頁跳轉(zhuǎn)回主頁面的時(shí)候需要主頁面保留搜索條件以及數(shù)據(jù)。
- 后臺(tái)系統(tǒng)常見的跳轉(zhuǎn)后添加頂部標(biāo)簽,標(biāo)簽之間切換期望保留數(shù)據(jù)。
弊端
- 不能保證系統(tǒng)的數(shù)據(jù)時(shí)效性。
- keep-alive 的本質(zhì)是保持頁面不銷毀,這樣會(huì)增加內(nèi)存的占用。
keep-alive的生命周期
- 初次進(jìn)入時(shí):created > mounted > activated;退出后觸發(fā) deactivated
- 再次進(jìn)入:會(huì)觸發(fā) activated;事件掛載的方法等,只執(zhí)行一次的放在 mounted 中;組件每次進(jìn)去執(zhí)行的方法放在 activated 中
項(xiàng)目實(shí)踐
- 更改HTML模板。
<keep-alive :include="cachViews">
<router-view :key="key" class="container" />
</keep-alive>
- 在路由中設(shè)置一個(gè)keepAlive
{
meta: {
keepAlive: true
}
path: 'home',
component: lazyLoad('home')
}
- 監(jiān)聽路由變化添加到全局狀態(tài)機(jī)中
watch: {
$route() {
if (this.$route.meta.keepAlive) {
this.addCachViews();
}
},
}
- 添加一個(gè)全局的beforeRouteLeave鉤子用于銷毀緩存頁面
Vue.mixin({
beforeRouteLeave(to, from, next) {
if (!from.meta.keepAlive) {
this.$destroy(true);
}
next();
},
})
為什么要這樣來銷毀緩存頁面而不使用exclude亦或是使用兩個(gè)router-view。
在一個(gè)嵌套三層的路由結(jié)構(gòu)下你會(huì)發(fā)現(xiàn)緩存可能失效了,原因是因?yàn)楦讣塀lank不存在于include中,你需要把父級加入到include。 但是我們只希望index被緩存,details不被緩存,但是父級有了緩存導(dǎo)致就算details不在include中也會(huì)被緩存。
這時(shí)候上面的鉤子就起到作用了,退出頁面的時(shí)候手動(dòng)銷毀details頁面
{
path: '/Layout',
name: 'Layout',
component: Layout, // 整個(gè)后臺(tái)項(xiàng)目的框架
children: [
{
path: 'Blank',
name: 'Blank',
component: Blank, // 空白頁面
children: [{
keepAlive: true,
path: 'index',
name: 'index',
component: index, // 主頁
}, {
path: 'details',
name: 'details',
component: details, // 詳情頁
}]
}
]
}
同時(shí)網(wǎng)上很多的解決方案都是用router-view如下。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
同樣以上面三層嵌套為例。這樣寫你會(huì)發(fā)現(xiàn)進(jìn)入到index進(jìn)入details再進(jìn)index這個(gè)時(shí)候index 的緩存被刷新了。
總結(jié):
1、多級嵌套導(dǎo)致緩存不生效,這個(gè)時(shí)候可能是因?yàn)槟銢]有把父級的空頁面加入到include中。
2.、include需要的name是組件的name,不是router name。
3、 多級嵌套兄弟頁面A需要緩存,B不需要緩存。同時(shí)只把A頁面添加到了include中但是B頁面也緩存了,那么應(yīng)該是因?yàn)樗麄兊母讣壖尤氲搅薸nclude中,需要手動(dòng)銷毀B頁面。