本文へジャンプ

KeepAlive

<KeepAlive> は、複数のコンポーネント間を動的に切り替えるときに、コンポーネントインスタンスを条件付きでキャッシュ可能にするビルトインコンポーネントです。

基本的な使い方

「コンポーネントの基礎」の章で、特別な要素 <component> を使用する、動的コンポーネントのための構文を導入しました:

template
<component :is="activeComponent" />

デフォルトでは、アクティブなコンポーネントのインスタンスは、別のコンポーネントに切り替えられたときにアンマウントされます。これにより、保持している変更された状態は失われてしまいます。このコンポーネントを再度表示すると、初期状態のみを持つ新しいインスタンスが作成されます。

下の例では、ステートフルなコンポーネントが 2 つあります。A にはカウンターがあり、B には v-model 経由でメッセージが同期された input があります。いずれかの状態を更新してコンポーネントを切り替えたあと、もう一度元のコンポーネントに切り替えてみてください:

Current component: A

count: 0

もう一度切り替えたとき、以前の状態がリセットされたことに気が付くと思います。

切り替え時に新しいコンポーネントインスタンスを作成するというのは、通常は役に立つ動作です。しかし、この場合には、2 つのコンポーネントインスタンスはアクティブでなくなった後にも状態を保持するのが望ましいです。この問題を解決するために、動的コンポーネントを <KeepAlive> というビルトインコンポーネントで包むことができます:

template
<!-- 非アクティブなコンポーネントはキャッシュされます! -->
<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

これで、コンポーネントを切り替えても状態が永続化されます。

Current component: A

count: 0

TIP

DOM 内テンプレート内で使用する場合は <keep-alive> として参照する必要があります。

Include / Exclude

デフォルトでは、<KeepAlive> はコンポーネント内のどんなコンポーネントでもキャッシュします。この動作は includeexclude props を使用してカスタマイズできます。どちらの props にも、カンマ区切りの文字列、RegExp、あるいは、そのいずれかの型を含む配列を指定できます:

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 props を使うと、キャッシュできるコンポーネントインスタンスの最大数を制限することができます。max が指定された場合、<KeepAlive>LRU キャッシュ のように動作します。つまり、キャッシュインスタンスの数が指定された最大数を越えようとした時点で、最も過去にアクセスされたキャッシュインスタンスが破棄され、新しいキャッシュ用のスペースが作られます。

template
<KeepAlive :max="10">
  <component :is="activeComponent" />
</KeepAlive>

キャッシュされたインスタンスのライフサイクル

コンポーネントインスタンスが DOM から削除されても <KeepAlive> によってコンポーネントツリーのキャッシュの一部である場合、コンポーネントインスタンスはアンマウントされる代わりに非アクティブ化状態に移行します。コンポーネントインスタンスが DOM にキャッシュツリーの一部として挿入されると、アクティブ化されます。

kept-alive コンポーネントは、これら 2 つの状態に対して、onActivated()onDeactivated() を使用してライフサイクルフックを登録できます:

vue
<script setup>
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
  // 最初のマウントと
  // キャッシュからの再挿入のたびに呼ばれる
})

onDeactivated(() => {
  // DOM から削除されてキャッシュに挿入されるときと
  // アンマウントされるときにも呼ばれる
})
</script>

kept-alive コンポーネントは、これら 2 つの状態に対して、activateddeactivated のフックを使用してライフサイクルフックを登録できます:

js
export default {
  activated() {
    // 最初のマウントと
    // キャッシュからの再挿入のたびに呼ばれる
  },
  deactivated() {
    // DOM から削除されてキャッシュに挿入されるときと
    // アンマウントされるときにも呼ばれる
  }
}

次のことに注意してください:

  • onActivatedactivated はマウント時にも呼ばれ、 onDeactivateddeactivated はアンマウント時にも呼ばれる。

  • 両方のフックは、<KeepAlive> でキャッシュされたルートコンポーネントだけではなく、キャッシュツリー内の子孫コンポーネントに対しても機能する。


関連ページ

KeepAliveが読み込まれました