KeepAlive
<KeepAlive>
是一個內置組件,它的功能是在多個組件間動態切換時緩存被移除的組件實例。
基本使用
在組件基礎章節中,我們已經介紹了通過特殊的 <component>
元素來實現動態組件的用法:
template
<component :is="activeComponent" />
默認情況下,一個組件實例在被替換掉後會被銷毀。這會導致它丟失其中所有已變化的狀態——當這個組件再一次被顯示時,會創建一個只帶有初始狀態的新實例。
在下面的例子中,你會看到兩個有狀態的組件——A 有一個計數器,而 B 有一個通過 v-model
同步 input 框輸入內容的文字展示。嘗試先更改一下任意一個組件的狀態,然後切走,再切回來:
Current component: A
Count: 0你會發現在切回來之後,之前已更改的狀態都被重置了。
在切換時創建新的組件實例通常是有意義的,但在這個例子中,我們的確想要組件能在被“切走”的時候保留它們的狀態。要解決這個問題,我們可以用 <KeepAlive>
內置組件將這些動態組件包裝起來:
template
<!-- 非活躍的組件將會被緩存! -->
<KeepAlive>
<component :is="activeComponent" />
</KeepAlive>
現在,在組件切換時狀態也能被保留了:
Current component: A
Count: 0TIP
在 DOM 內模板中使用時,它應該被寫為 <keep-alive>
。
包含/排除
<KeepAlive>
默認會緩存內部的所有組件實例,但我們可以通過 include
和 exclude
prop 來定製該行為。這兩個 prop 的值都可以是一個以英文逗號分隔的字符串、一個正則表達式,或是包含這兩種類型的一個數組:
template
<!-- 以英文逗號分隔的字符串 -->
<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>
<!-- 正則表達式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
<component :is="view" />
</KeepAlive>
<!-- 數組 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
<component :is="view" />
</KeepAlive>
它會根據組件的 name
選項進行匹配,所以組件如果想要條件性地被 KeepAlive
緩存,就必須顯式聲明一個 name
選項。
TIP
在 3.2.34 或以上的版本中,使用 <script setup>
的單文件組件會自動根據文件名生成對應的 name
選項,無需再手動聲明。
最大緩存實例數
我們可以通過傳入 max
prop 來限制可被緩存的最大組件實例數。<KeepAlive>
的行為在指定了 max
後類似一個 LRU 緩存:如果緩存的實例數量即將超過指定的那個最大數量,則最久沒有被訪問的緩存實例將被銷燬,以便為新的實例騰出空間。
template
<KeepAlive :max="10">
<component :is="activeComponent" />
</KeepAlive>
緩存實例的生命週期
當一個組件實例從 DOM 上移除但因為被 <KeepAlive>
緩存而仍作為組件樹的一部分時,它將變為不活躍狀態而不是被卸載。當一個組件實例作為緩存樹的一部分插入到 DOM 中時,它將重新被激活。
一個持續存在的組件可以通過 onActivated()
和 onDeactivated()
註冊相應的兩個狀態的生命週期鉤子:
vue
<script setup>
import { onActivated, onDeactivated } from 'vue'
onActivated(() => {
// 調用時機為首次掛載
// 以及每次從緩存中被重新插入時
})
onDeactivated(() => {
// 在從 DOM 上移除、進入緩存
// 以及組件卸載時調用
})
</script>
請注意:
onActivated
在組件掛載時也會調用,並且onDeactivated
在組件卸載時也會調用。這兩個鉤子不僅適用於
<KeepAlive>
緩存的根組件,也適用於緩存樹中的後代組件。
參考