在使用基于Vue的單頁面富應用的開發中,總會面向這樣的産品需求,既從清單頁跳轉詳情頁面,傳回時需要儲存清單頁的狀态。
這種場景下,若是講資料寫入到全局狀态中,總會面臨複雜的頁面路由判斷來清楚和存儲頁面狀态。
keep-alive簡介
相較于複雜的全局狀态管理,Vue在2.x版本中将keep-alive這一元件屬性擴充成了内置的抽象元件<keep-alive>,它自身不會渲染一個 DOM 元素,也不會出現在父元件鍊中。當元件在 <keep-alive> 内被切換,它的 activated 和 deactivated 這兩個生命周期鈎子函數将會被對應執行。使得被keep-alive元件包裹的元件的狀态得以保留也避免了該元件的重複渲染。
keep-alive元件應用也相當的簡單,如下:
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多個條件判斷的子元件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
與vue-router的結合
當keep-alive與vue-router結合時,就完全比對我們頁面緩存儲存狀态以及資料的這一個使用場景了。
<keep-alive>
<router-view>
<!-- 所有路徑比對到的視圖元件都會被緩存! -->
</router-view>
</keep-alive>
将router-view作為被keep-alive包裹的元件,預設路由下的所有頁面都将被緩存,所有頁面的狀态都會被保留。
那麼大家這個時候就會有個疑問,我并不想保留所有的頁面呀,我僅僅是想保留幾個業務場景,就像文頭那種由清單頁進入詳情頁,再由詳情頁傳回清單頁時的狀态保留。
vue在keep-alive元件提供了include 和 exclude 屬性允許元件有條件地緩存。二者都可以用逗号分隔字元串、正規表達式或一個數組來表示
// 元件 app-rank
export default {
name: 'app-rank',
data () {
return {}
}
}
<keep-alive include="app-rank">
<router-view>
<!-- 隻有路徑比對到的視圖 app-rank 元件會被緩存! -->
</router-view>
</keep-alive>
當場景稍微複雜,如同級目錄之間跳轉無需儲存狀态,僅需在跳轉詳情頁面是儲存狀态時,這樣就需要動态管理keep-alive的緩存。
複雜場景下的keep-alive的使用有一下兩種方案
方案一:
<keep-alive :include="includeRoute">
<router-view>
<!-- 隻有路徑比對到的includeRoute表達式 元件會被緩存! -->
</router-view>
</keep-alive>
方案二:
路由中router.meta 屬性中增加是否緩存頁面元件的相應字段,優點是便于管理上下遊頁面元件的緩存。
{
path: '/',
meta: {
title: '應用排行',
keepAlive: true
},
name:'appRankList',
component: (resolve) => require(['./views/app-rank.vue'], resolve)
}
路由中meta下增加keepAlive的屬性,以便于route對象中讀取。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
這樣keep-alive中出現的就是需要緩存的路由頁面,當需要在離開頁面前改變去往頁面的緩存狀态時,僅需要在頁面中添加beforeRouteLeave
export default {
data() {
return {
};
},
beforeRouteLeave(to, from, next) {
// 設定下一個路由的 meta
to.meta.keepAlive = false;
next();
}
}
綜上所述,Vue中頁面的緩存無需太複雜的狀态管理就可以達到緩存頁面狀态防止重複渲染的作用。