はじめに
はじめまして、学生エンジニアの@huyunokiです。
Vue.jsでコンポーネントを分割した際、必ず直面するのが「どうやってデータをやり取りするか?」という問題です。
この記事ではVueの基本原則である「Props Down / Events Up(単一方向データフロー)」の仕組みを、初学者から経験者まで再確認できる形で端的に解説します。
1. 大原則:単一方向データフロー (One-Way Data Flow)
Vueではデータの流れが一方通行に制限されています。これにより「どこでデータが変わったか」を追いやすくしています。
- Props Down: 親から子へデータを流す(読み取り専用)
- Events Up: 子から親へイベントを通知し、データの更新を依頼する
2. 親から子へ:props(データの伝達)
親コンポーネントが持っているデータを、子コンポーネントに「属性」として渡す仕組みです。
原理
子コンポーネントは受け取った props を直接書き換えることはできません。これは、親のデータが予期せず書き換わるのを防ぐための安全装置です。
実装手順
-
親: 子コンポーネントをインポートし、テンプレート内で
v-bind(または:)を使って値を渡す。 -
子:
propsオプションで、受け取るデータの名前と型を宣言する。
親コンポーネント (Parent.vue)
<template>
<div>
<!-- 子の属性「user-name」に親のデータ「name」を渡す -->
<ChildComponent :user-name="name" />
</div>
</template>
<script>
export default {
data() {
return { name: '寺田' }
}
}
</script>
子コンポーネント (Child.vue)
export default {
// propsとして受け取る名前と型を定義
props: {
userName: String
}
}
3. 子から親へ:$emit(イベントの通知)
子が「何かが起きた(ボタンが押された等)」というイベントを発行し、親に知らせる仕組みです。
原理
子は親のデータを直接変える代わりに、「メッセージを送るだけ」にします。そのメッセージを受け取った親が、自分のデータを自分で更新します。
実装手順
-
子: 任意のタイミング(クリック時など)で
this.$emit('イベント名', 渡したい値)を実行。 -
親: 子コンポーネントのタグに
@イベント名="実行したいメソッド名"を記述する。
子コンポーネント (Child.vue)
<template>
<!-- ボタンを押したら「update-name」というイベントを親に送る -->
<button @click="$emit('update-name', '大西')">名前を変更</button>
</template>
親コンポーネント (Parent.vue)
<template>
<div>
<p>現在の名前: {{ name }}</p>
<!-- 子からのイベント「update-name」をキャッチしてメソッドを動かす -->
<ChildComponent @update-name="changeName" />
</div>
</template>
<script>
export default {
data() {
return { name: '寺田' }
},
methods: {
changeName(newName) {
this.name = newName; // 親が自分のデータを更新
}
}
}
</script>
4. props と $emit のまとめ表
| 項目 | props | $emit |
|---|---|---|
| 方向 | 親 → 子 (Down) | 子 → 親 (Up) |
| 役割 | 値を受け渡す | イベント(通知)を送る |
| データの性質 | 読み取り専用(Immutable) | 親の処理を発火させるトリガー |
| 主要な構文 | v-bind:prop名 |
@イベント名 / this.$emit\
|
結論:なぜこの形なのか?
もし子が親のデータを自由に書き換えられたら、大規模なアプリでは「誰がいつデータを壊したか」が分からなくなります。
「データは親が持ち、更新の判断も親がする。子は表示と通知に徹する」
このルールを守ることが、バグの少ないクリーンなVue開発への第一歩となるみたいです。