概要
vue.jsとtypescriptでアプリを制作中、親-子コンポーネントのデータ連携はできたが、親-子-孫コンポーネントのデータ連携に少し時間がかかってしまった。
そこで、階層の深いコンポーネント間のデータ連携についてまとめていきます。
親クラス
Parent.vue
<template>
<!-- 1, 2 -->
<Child
:name="name"
@nameFromChild="name=$event">
</Child>
</template>
<script lang="ts">
import {Vue, Component} from 'vue'
import Child from 'components/Child.vue'
@Component({
components: {
Child
},
})
class Parent extends Vue {
/** 名前(変更対象) */
private name = "";
}
</script>
- Childコンポーネントに空のname=""を渡す
- 子コンポーネントが"nameFromChild"で発火したイベントを受け取り、name変数に変更された値が入る
子クラス
Child.vue
<template>
<!-- 2, 3 -->
<GrandChild
:grandChildName="childName"
@grandChildName="childName = $event">
</GrandChild>
</template>
<script lang="ts">
import {Vue, Component} from 'vue'
import Child from 'components/Child.vue'
@Component({
components: {
Child
},
})
class Child extend Vue {
/** 1 */
@Prop()
private name = "";
/** 3 */
get childName(){
return this.name;
}
/** 4 */
set childName(name: string){
this.$emit('nameFromChild', name);
}
}
</script>
- 親コンポーネントからProp関数で空のname=""を受け取る
- GrandChildコンポーネントに空のchildName=this.nameを渡す
- 孫コンポーネントが"nameFromGrandChild"で発火したイベントを受け取り、childNameに変更された値が渡される
- 孫コンポーネントからgrandChildNameでイベントが発火される。childNameが孫から渡された値($event)によって変更された場合、下記ではemit関数で親コンポーネントにイベントを発火し、書き換えられたnameを渡す
孫クラス
GrandChild.vue
<template>
<v-text-field
:value="grandChildName"
@input="$emit('nameFromGrandChild', $event)">
</v-text-field>
</template>
<script lang="ts">
import {Vue, Prop} from 'vue'
class GrandChild extends Vue {
/** 1 */
@Prop()
private grandChildName?: string;
}
</script>
- 子から渡ってきた空のgrandChildName=""
- emit関数を使用し、テキストフィールドが変更(input)されたら、変更された値($event)を引数を持ってイベントを発火