Vue.js の keep-alive でコンポーネントをキャッシュする

最終更新日
2017.10.15

keep-alive を使うと状態を初期化せずにコンポーネントの切り替えが出来る。

コンポーネントの状態をキャッシュ

通常キーの設定されたコンポーネントを v-if で切り替えたり、 :is="component" で動的に切り替えた場合毎回ライフサイクルが発生して状態は初期化されます。

<div id="app">
  <button @click="current='child1'">child1</button>
  <button @click="current='child2'">child2</button>
  <button @click="current=null" v-show="current">close</button>
  <child-comp v-if="current=='child1'" key="child1"></child-comp>
  <child-comp v-if="current=='child2'" key="child2"></child-comp>
</div>
<script type="text/x-template" id="template-tab">
  <div>
    <h2>{{ $vnode.key }}</h2>
    <p>Count: {{ count }} <button @click="count++">click</button></p>
  </div>
</script>
Vue.component('child-comp', {
  template: '#template-tab',
  data() {
    return {
      count: 0
    }
  },
  created() {
    console.log('created')
  },
  beforeDestroy() {
    console.log('beforeDestroy')
  },
  activated() {
    console.log('activated')
  },
  deactivated() {
    console.log('deactivated')
  }
})
new Vue({
  el: '#app',
  data: {
    current: null
  }
})

上の例では表示してカウンターを増加させても切り替えの度に「0」に戻ります。

コンポーネントを以下のように keep-alive で囲むと切り替えても状態を維持します。

<keep-alive>
  <child-comp v-if="current=='child1'" key="child1"></child-comp>
  <child-comp v-if="current=='child2'" key="child2"></child-comp>
</keep-alive>

特定のコンポーネントだけキャッシュさせる

<keep-alive> に囲まれている場合子コンポーネントもキャッシュされます。以下のオプションプロパティで特定のコンポーネントだけを許可・除外出来ます。

  • include - 指定したコンポーネントのみキャッシュする
  • exclude - 指定したコンポーネントのみキャッシュしない

値には正規表現が使えます。その場合は式タイプにする。

<keep-alive :include="/^modal-/"></keep-alive>

キャッシュモードで呼ばれているかを確認する

以下のライフサイクルフックを使用して状態を確認出来ます。

  • activated - キャッシュモードでコンポーネントの使用を開始した時
  • deactivated - キャッシュモードでコンポーネントの使用を終了した時

上のデモを実行するとコンソール画面からどのようにライフサイクルが発生しているか確認出来ます。

ルータービューの状態をキャッシュ

<router-view> もコンポーネントなので同じようにキャッシュすることが出来ます。

上のデモはルーターを使用して掲示板とフォームでページを分けています。<keep-alive> を使うとページを切り替えて掲示板の内容を確認しながらコメントを入力出来ます。

transition との併用

keep-aliveを内側に書く。

<transition name="fade">
  <keep-alive>
    <router-view></router-view>
  </keep-alive>
</transition>

他にも <keep-alive> に囲まれているコンポーネント自体が不要になる時までライフィサイクルが発生しなくなりコンポーネントの状態を維持しながらページを遷移するので、API との不要な通信を減らすことが出来ます。