Vueの動的コンポーネント(typescript)
Posted
Vue.jsの動的コンポーネントについて。
公式リファレンス:
https://jp.vuejs.org/v2/guide/components-dynamic-async.html
動的コンポーネント
例えば、ボタンを3つ設置し、そのボタン操作によって表示するコンポーネント(子供)を変化させたい、などの場合、 動的なコンポーネントが欲しくなる。
動的なコンポーネントは <components>
を使って表現する。このタグと置き換わる子供のコンポーネントの指定は、
v-bind:is (:is)
で指定することが出来、ここには子供のコンポーネント(オブジェクト)を与える。
<template>
<div class="hello">
<components :is="childComponent"></components>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Child from './Child.vue';
@Component({
components: {
Child
},
})
export default class HelloWorld extends Vue {
private childComponent: object = Child;
}
</script>
上記の場合、 <components>
が <child>
に置き換わると考えれば良い。
あとはお好みで、 childComponent
の値を変化させるイベントを仕込めば良い。
一度生成した子コンポーネントをキャッシュに保存したい
下記のようなコンポーネントがあったとする。
<template>
<div class="hello">
<button @click="clickBtn(1)">button1</button><br>
<button @click="clickBtn(2)">button2</button><br>
<components :is="childComponent"></components>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import ChildA from './ChildA.vue';
import ChildB from './ChildB.vue';
@Component({
components: {
ChildA,
ChildB,
}
})
export default class HelloWorld extends Vue {
private childComponent: object = ChildA;
private clickBtn(componentNumber: number): void {
switch (componentNumber) {
case 1 :
this.childComponent = ChildA;
break;
case 2 :
this.childComponent = ChildB;
break;
}
}
}
</script>
上記のコンポーネントにはボタンが2つ設置刺されており、上のボタンを押すと ChildA
が、下のボタンを押すと ChildB
が
childComponent
フィールドに格納され、それが <components>
に与えられて子コンポーネントを表示する。(ボタンを押すと切り替わる)
上記の場合、
- ボタンを押す
- 子コンポーネント(オブジェクト)を生成する
childComponent
にオブジェクトを代入childComponent
の変化により表示を更新
という手順を繰り返す。
特に問題なさそうだが、2つのボタンを交互に押した時、
- ボタンBを押す
- ChildBオブジェクトが生成される
childComponent
にオブジェクトが代入される- ボタンAを押す
- ChildAオブジェクトが生成される
childComponent
にオブジェクトが代入される- ボタンBを押す
- ChildBオブジェクトが生成される
childComponent
にオブジェクトが代入される
…
という繰り返しが行われる。せっかく、一度 ChildB
を生成したのに、そこからさらに ChildA
に切り替わると
ChildB
は破棄される。
これだともったいないので、一度作った子コンポーネントはキャッシュして持っておきたい。
そんな時に使えるのが <keep-alive>
である。
<template>
<div class="hello">
<button @click="clickBtn(1)">button1</button><br>
<button @click="clickBtn(2)">button2</button><br>
<keep-alive>
<components :is="childComponent"></components>
</keep-alive>
</div>
</template>
これで、一度生成した子コンポーネントはキャッシュに保存され、その手順は、
- ボタンBを押す
- ChildBオブジェクトが生成される
childComponent
にオブジェクトが代入される- ボタンAを押す
- ChildAオブジェクトがキャッシュから取り出される
childComponent
にオブジェクトが代入される- ボタンBを押す
- ChildBオブジェクトがキャッシュから取り出される
childComponent
にオブジェクトが代入される
となる。これなら、子コンポーネントの切り替え前をそのまま保持させておくことも出来る。