vue開發之keep-alive
概念
keep-alive 是vue的內建元件,當它包裹動態元件時,會快取不活動的元件例項,而不是銷燬它們。和 transition 相似,keep-alive 是一個抽象元件:它自身不會渲染成一個 DOM 元素,也不會出現在父元件鏈中。
作用
在元件切換過程中將狀態保留在記憶體中,防止重複渲染DOM,減少載入時間及效能消耗,提高使用者體驗性
原理
在 created函式呼叫時將需要快取的 VNode 節點儲存在 this.cache 中/在 render(頁面渲染) 時,如果 VNode 的 name 符合快取條件(可以用 include 以及 exclude 控制),則會從 this.cache 中取出之前快取的 VNode 例項進行渲染。
VNode:虛擬DOM,其實就是一個js物件
Props
include - 字串或正則表示式。只有名稱匹配的元件會被快取。
exclude - 字串或正則表示式。任何名稱匹配的元件都不會被快取。
max - 數字。最多可以快取多少元件例項。
生命週期函式
1. activated
在 keep-alive 元件啟用時呼叫
該鉤子函式在伺服器端渲染期間不被呼叫
2. deactivated
在 keep-alive 元件停用時呼叫
該鉤子在伺服器端渲染期間不被呼叫
被包含在 keep-alive 中建立的元件,會多出兩個生命週期的鉤子: activated 與 deactivated
使用 keep-alive 會將資料保留在記憶體中,如果要在每次進入頁面的時候獲取最新的資料,需要在 activated 階段獲取資料,承擔原來 created 鉤子函式中獲取資料的任務。
注意:只有元件被 keep-alive 包裹時,這兩個生命週期函式才會被呼叫,如果作為正常元件使用,是不會被呼叫的,以及在 2.1.0 版本之後,使用 exclude 排除之後,就算被包裹在 keep-alive 中,這兩個鉤子函式依然不會被呼叫!另外,在服務端渲染時,此鉤子函式也不會被呼叫。
快取所有頁面
1. 在 App.vue裡面
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</div >
</template>
<script>
export default {
name: 'App'
}
</script>
根據條件快取頁面
1. 在 App.vue 裡面
<template>
<div id="app">
// 1. 將快取 name 為 test 的元件
<keep-alive include='test'>
<router-view/>
</keep-alive>
// 2. 將快取 name 為 a 或者 b 的元件,結合動態元件使用
<keep-alive include='a,b'>
<router-view/>
</keep-alive>
// 3. 使用正則表示式,需使用 v-bind
<keep-alive :include='/a|b/'>
<router-view/>
</keep-alive>
// 5.動態判斷
<keep-alive :include='includedComponents'>
<router-view/>
</keep-alive>
// 5. 將不快取 name 為 test 的元件
<keep-alive exclude='test'>
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
結合Router,快取部分頁面
1. 在 router 目錄下的 index.js檔案裡
import Vue from 'vue'
import Router from 'vue-router'
const Home = resolve => require(['@/components/home/home'], resolve)
const Goods = resolve => require(['@/components/home/goods'], resolve)
const Ratings = resolve => require(['@/components/home/ratings'], resolve)
const Seller = resolve => require(['@/components/home/seller'], resolve)
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home,
redirect: 'goods',
children: [
{
path: 'goods',
name: 'goods',
component: Goods,
meta: {
keepAlive: false // 不需要快取
}
},
{
path: 'ratings',
name: 'ratings',
component: Ratings,
meta: {
keepAlive: true // 需要快取
}
},
{
path: 'seller',
name: 'seller',
component: Seller,
meta: {
keepAlive: true // 需要快取
}
}
]
}
]
})
2. 在 App.vue 裡面
<template>
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
使用 router.meta 拓展
假設這裡有 3 個路由: A、B、C。
需求:
預設顯示 A
B 跳到 A,A 不重新整理
C 跳到 A,A 重新整理
實現方式:
1. 在 A 路由裡面設定 meta 屬性
{
path: '/',
name: 'A',
component: A,
meta: {
keepAlive: true // 需要被快取
}
}
2. 在 B 元件裡面設定 beforeRouteLeave
export default {
data() {
return {};
},
methods: {},
beforeRouteLeave(to, from, next) {
// 設定下一個路由的 meta
to.meta.keepAlive = true; // 讓 A 快取,即不重新整理
next();
}
};
3. 在 C 元件裡面設定 beforeRouteLeave
export default {
data() {
return {};
},
methods: {},
beforeRouteLeave(to, from, next) {
// 設定下一個路由的 meta
to.meta.keepAlive = false; // 讓 A 不快取,即重新整理
next();
}
};
這樣便能實現 B 回到 A,A 不重新整理;而 C 回到 A 則重新整理。
2.5.0 版本新增max
最多可以快取多少元件例項。一旦這個數字達到了,在新例項被建立之前,已快取元件中最久沒有被訪問的例項會被銷燬掉。
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
注意
注意這個 <keep-alive> 要求被切換到的元件都有自己的名字,不論是通過元件的 name 選項還是區域性/全域性註冊。