VueJS 速習チュートリアル

Vue ダイナミックコンポーネント

ダイナミックコンポーネント(Dynamic Components)を使用すると、ブラウザのタブのように、is 属性を利用してページ内の表示要素を動的に切り替えることができます。

1. コンポーネントタグと 'is' 属性

ダイナミックコンポーネントを作成するには、現在アクティブなコンポーネントを表す <component> タグを使用します。is 属性を v-bind で特定の値に紐付け、その値を表示したいコンポーネント名に変更することで、表示を切り替えます。

1.1 実装例

この例では、<component> タグが comp-one または comp-two コンポーネントのプレースホルダとして機能します。is 属性は、comp-onecomp-two のいずれかの値を保持する算出プロパティ(computed) activeComp を監視しています。ボタンをクリックすると toggleValue が反転し、アクティブなコンポーネントが切り替わります。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <p>App.vue が表示するコンポーネントを切り替えます。</p>
  <button @click="toggleValue = !toggleValue">
    コンポーネントを切り替える
  </button>
  <component :is="activeComp"></component>
</template>

<script>
  export default {
    data() {
      return {
        // 切り替え用のフラグ
        toggleValue: true
      }
    },
    computed: {
      activeComp() {
        if(this.toggleValue) {
          return 'comp-one'
        }
        else {
          return 'comp-two'
        }
      }
    }
  }
</script>

2.  による状態の保持

2.1 実装例(KeepAliveあり)

これで、コンポーネントはユーザーの入力を記憶するようになります。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <p>App.vue が表示するコンポーネントを切り替えます。</p>
  <button @click="toggleValue = !toggleValue">
    コンポーネントを切り替える
  </button>
  
  <KeepAlive>
    <component :is="activeComp"></component>
  </KeepAlive>
</template>

3. 'include' および 'exclude' 属性

デフォルトでは、<KeepAlive> タグ内にあるすべてのコンポーネントがキャッシュ(状態保持)の対象となります。
しかし、include または exclude 属性を使用することで、特定のコンポーネントのみをキャッシュ対象に指定したり、対象から外したりすることができます。

これらの属性を使用する場合、コンポーネント側の定義で name オプションを使って名前を指定する必要があります。

CompOne.vue:

<script>
  export default {
    name: 'CompOne',
    data() {
      return {
        imgSrc: 'img_question.svg'
      }
    }
  }
</script>

3.1 include の使用例

<KeepAlive include="CompOne"> と指定すると、CompOne コンポーネントだけがその状態(以前の入力内容など)を保持します。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <p>App.vue が表示するコンポーネントを切り替えます。</p>
  <button @click="toggleValue = !toggleValue">
    コンポーネントを切り替える
  </button>
  
  <KeepAlive include="CompOne">
    <component :is="activeComp"></component>
  </KeepAlive>
</template>

3.2 exclude の使用例

逆に exclude を使うと、特定のコンポーネントをキャッシュから除外できます。<KeepAlive exclude="CompOne"> の場合、CompTwo だけが状態を保持します。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <p>App.vue が表示するコンポーネントを切り替えます。</p>
  <button @click="toggleValue = !toggleValue">
    コンポーネントを切り替える
  </button>
  
  <KeepAlive exclude="CompOne">
    <component :is="activeComp"></component>
  </KeepAlive>
</template>

includeexclude はどちらも、カンマ区切りで複数のコンポーネントを指定できます。以下の例では、3つのコンポーネントを使用して動作を確認します。

3.3 複数指定の例

<KeepAlive include="CompOne, CompThree"> とすると、CompOneCompThree の両方が状態を保持します。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <button @click="compNbr++">
    次のコンポーネントへ
  </button>
  
  <KeepAlive include="CompOne,CompThree">
    <component :is="activeComp"></component>
  </KeepAlive>
</template>

4. 'max' 属性

<KeepAlive> タグに max 属性を指定することで、ブラウザが保持するコンポーネントの状態の数を制限できます。これはメモリ使用量を最適化したい場合に有効です。

4.1 実装例

<KeepAlive :max="2"> と指定すると、ブラウザは直近に訪れた2つのコンポーネントの入力内容のみを記憶します。3つ目のコンポーネントに移動すると、最も古いキャッシュが破棄されます。

App.vue:

<template>
  <h1>ダイナミックコンポーネント</h1>
  <label><input type="radio" name="rbgComp" v-model="compName" :value="'comp-one'"> 1つ目</label>
  <label><input type="radio" name="rbgComp" v-model="compName" :value="'comp-two'"> 2つ目</label>
  <label><input type="radio" name="rbgComp" v-model="compName" :value="'comp-three'"> 3つ目</label>
  
  <KeepAlive :max="2">
    <component :is="activeComp"></component>
  </KeepAlive>
</template>