1.@Propコンポーネント間のデータの受け渡し(親→子)
Vue.js+Typescriptde+vue-property-decoratorでpropsとemitを使うときの備忘録。
<Prop編>
親コンポーネントでは、子コンポーネントタグに子コンポーネントのプロパティ名をケバブケースで命名する。
(今回は、子コンポーネントのプロパティ名は「YourDinner
」のため、親コンポーネントの属性名は「your-dinner
」になる。)
<Component your-dinner="カレーライス"></Component>
⬇︎ Props down
子コンポーネントでは、@Propデコレーターをつけたプロパティで受け取る。
@Prop({default:"なし"})
yourDinner!: string; //←上記の親コンポーネントで渡した「カレーライス」が入る。
親コンポーネントから渡ってくる値を受け取るyourDinner
変数を定義。
値が渡ってこなかった場合は、default内の値がyourDinner
変数に代入される。
デフォルト値を設定しない場合は以下のように()内に何も入れなくていい。
@Prop()
また、子コンポーネントでは今まで通り以下のように初期化はしない。
yourName="";
このようにしてしまうと、毎回yourName
に空文字が代入されて、親コンポーネントから値が渡されない。
しかし、空文字で初期化をしないと、トランスコンパイル時に「初期化されていない」というエラーが出てしまう。
「!」マークをつけることで、「初期化されていないが問題ない」ということをトランスコンパイラに伝えることができる。
また、TypeScriptでは初期値で変数の方を推論するが、初期化していないため、「:string
」をつけて型指定をする。
<サンプルコード>
<template>
<div class="sample">
<div>あなたの夕食は、{{yourDinner}}です。</div>
</div>
</template>
<script lang=ts>
import { Prop, Component, Vue } from "vue-property-decorator";
@Component
export default class CompPropsYourDinner extends Vue {
@Prop({ default:"なし"})
yourDinner!:string;
}
</script>
@Propデコレーターを使用するためには、"vue-property-decorater"
からインポートする必要がある。
<template>
<div class="sample">
<CompPropsYourDinner your-dinner="カレーライス"></CompPropsYourDinner>
<CompPropsYourDinner your-dinner="親子丼"></CompPropsYourDinner>
<CompPropsYourDinner></CompPropsYourDinner>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import CompPropsYourDinner from "@/components/sample/ComPropsYourDinner.vue";
@Component({
Component: {
CompPropsYourDinner,
},
})
export default class PropsParent extends Vue {}
</script>
3行目と4行目でそれぞれ、「カレーライス」と「親子丼」を子コンポーネントに渡している。
5行目ではyour-dinner
属性が存在せず、値を渡していないのでデフォルト値の「なし」がyoueDinner
に入ることになる。
2.@Emit コンポーネント間のデータの受け渡し(子→親)
親コンポーネントで子コンポーネントで発生したイベントを拾う。
例)モーダル画面をクローズする場合
<LogoutModal v-on:close-modal="closeModal"></LogoutModal>
⬆︎
子コンポーネントでは@Emitデコレーターをつけたメソッドでイベントを発生させる。
<button class="btn" vclick="closeModal">モーダルを閉じる</button>
@Emit()
public closeModal): void {
console.log("close-modalイベント発生");
}
子コンポーネントのcloseModal()
メソッドに@Emit()デコレーターを付けることで、close-modal()
イベントが発生して、親コンポーネントに伝わる。
HTMLの特性で大文字、小文字を区別しないので、以下のようにかくことになる。
メソッド名:closeModal
(キャメルケース)←子コンポーネント
イベント名:close-modal
(ケバブケース)←親コンポーネント
<サンプルコード>
<template>
<div class="sample">
<button class="btn" v-on:click="closeModal">モーダルを閉じる</button>
</div>
</template>
<script lang="ts">
import { Emit, Component, Vue } from "vue-property-decorator";
@Component
export default class CompModalEmit extends Vue {
@Emit()
closeModal(): void {
console.log("close-modalイベント発生!");
}
}
</script>
closeModal()
メソッドについている@Emitデコレータは、イベントを発生させるデコレータで、同じメソッド名のイベントが発生して親コンポーネントに伝わる。
(このとき、子コンポーネントではキャメルケースのメソッド名だが、親コンポーネントではケバブケースに変換される)
<template>
<div class="sample">
<button @click="openModal">モーダルを開く</button>
<CompModalEmit v-on:close-modal="closeModal" v-if="isModalOpen">
</CompModalEmit>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import CompModalEmit from "../../components/sample/CompModalEmit.vue";
@Component({
Components: {
CompModalEmit,
},
})
export default class EmitParent extends Vue {
//モーダルの表示ステータス
private isModalOpen = false;
//モーダルを開く処理
openModal(): void {
this.isModalOpen = true;
}
//モーダルを閉じる処理
closeModal(): void {
this.isModalOpen = false;
}
}
</script>
v-on:close-modal="closeModal
で子コンポーネントで発生したclose-modal()
イベントを拾って、親コンポーネントのcloseModal()
メソッドを呼ぶ。
まとめ
データの受け渡しをするときは、
・親コンポーネントは、ケバブケース
・子コンポーネントは、キャメルケース
でメソッド名を書く。
親から子はPropで、子から親はEmit。