Vue.jsの$emit完全ガイド|親子コンポーネント間で値を渡す方法

Vue.jsでコンポーネントを使って開発していると、必ずといってよいほど出てくるのが親コンポーネントと子コンポーネントのデータ受け渡しです。
特に、子コンポーネントで起きた操作や入力内容を親コンポーネントに伝えたい場面では、$emit が重要な役割を果たします。

たとえば、次のようなケースです。

  • 子コンポーネントのボタンクリックを親に通知したい

  • フォーム入力の変更を親に渡したい

  • 子コンポーネントで選択した値を親側で管理したい

  • モーダルを閉じる処理を親側で制御したい

  • 再利用コンポーネントからイベントを発火して親で受け取りたい

Vue.jsでは、基本的にデータは親から子へ props で渡し、子から親へはイベントで通知するという流れで設計します。
この「子から親への通知」を実現するのが $emit です。

しかし初心者のうちは、次のような疑問を持ちやすいです。

  • $emit は何のために使うのか

  • props とはどう違うのか

  • $emit で値を渡すにはどう書けばいいのか

  • 複数の値を渡せるのか

  • v-model$emit はどう関係しているのか

  • Composition API ではどう書くのか

  • $emit が動かないときは何を確認すればよいのか

この記事では、Vue.jsの $emit について、基礎から実践、よくあるミス、Composition APIでの書き方、v-modelとの関係、エラー時の対処法までできるだけわかりやすく解説します。
「なんとなく使う」のではなく、なぜそう書くのかまで理解できるように丁寧に整理していきます。


$emitとは何か

$emit は、子コンポーネントから親コンポーネントへイベントを発火するための仕組みです。

Vue.jsでは、親子コンポーネント間のデータの流れは次のように考えるのが基本です。

  • 親 → 子 : props で値を渡す

  • 子 → 親 : $emit でイベントを通知する

つまり、$emit は単純に「値を直接送る」というより、
子がイベントを発生させ、そのイベントに付随する値を親に渡すものです。

たとえば、子コンポーネント側で次のように書くとします。

this.$emit('save')

これは、「save というイベントが起きた」ということを親に知らせています。

さらに値も渡したいなら、次のように書けます。

this.$emit('save', '送信データ')

この場合、親は save イベントを受け取りつつ、そのときのデータも一緒に受け取れます。


なぜ$emitが必要なのか

Vue.jsでは、コンポーネントを再利用可能に保つために、子コンポーネントが親の状態を直接書き換えない設計が推奨されます。

たとえば、子コンポーネントの中で親のデータを直接変更しようとすると、責務が曖昧になり、コードの見通しが悪くなります。
そのため、子は「こういう出来事が起きました」と親に伝えるだけにして、実際の状態管理は親が行うのが基本です。

この考え方には次のようなメリットがあります。

  • コンポーネントの責務が明確になる

  • 再利用しやすくなる

  • データの流れがわかりやすくなる

  • デバッグしやすくなる

  • 保守しやすくなる

つまり $emit は、Vue.jsらしい一方向データフローを守るための重要な仕組みです。


propsと$emitの違い

初心者が最初に混乱しやすいので、ここで整理しておきます。

props

親から子へデータを渡すための仕組みです。

<ChildComponent :message="parentMessage" />

子コンポーネント側では、props で受け取ります。

props: {
message: String
}

$emit

子から親へイベントを通知するための仕組みです。

this.$emit('update-message', '新しい値')

親コンポーネントでは、そのイベントを受け取ります。

<ChildComponent @update-message="handleUpdateMessage" />

つまり、

  • 親から子へ渡すのは props

  • 子から親へ返すのは $emit

という役割分担になります。


最も基本的な$emitの使い方

まずは最小構成で見てみましょう。


子コンポーネント側

<template>
<button @click="sendMessage">親に通知する</button>
</template>

<script>
export default {
methods: {
sendMessage() {
this.$emit('notify')
}
}
}
</script>

この子コンポーネントでは、ボタンをクリックすると notify イベントを発火しています。


親コンポーネント側

<template>
<ChildComponent @notify="handleNotify" />
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
},
methods: {
handleNotify() {
alert('子コンポーネントから通知を受け取りました')
}
}
}
</script>

親は @notify="handleNotify" と書くことで、子から発火された notify イベントを受け取っています。


$emitで値を渡す方法

イベントだけでなく、値も一緒に親へ渡したい場面は非常に多いです。
その場合は、$emit の第2引数以降にデータを指定します。


子コンポーネント側

<template>
<button @click="sendMessage">値を渡す</button>
</template>

<script>
export default {
methods: {
sendMessage() {
this.$emit('send-data', 'こんにちは、親コンポーネント')
}
}
}
</script>


親コンポーネント側

<template>
<ChildComponent @send-data="handleSendData" />
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
},
methods: {
handleSendData(message) {
console.log(message)
}
}
}
</script>

この場合、親の handleSendData は、子から渡された 'こんにちは、親コンポーネント' を受け取れます。


フォーム入力値を親へ渡す例

$emit は、フォーム部品を自作するときによく使います。

子コンポーネント

<template>
<input type="text" @input="handleInput" />
</template>

<script>
export default {
methods: {
handleInput(event) {
this.$emit('input-change', event.target.value)
}
}
}
</script>

親コンポーネント

<template>
<div>
<ChildInput @input-change="updateValue" />
<p>入力された値: {{ inputValue }}</p>
</div>
</template>

<script>
import ChildInput from './ChildInput.vue'

export default {
components: {
ChildInput
},
data() {
return {
inputValue: ''
}
},
methods: {
updateValue(value) {
this.inputValue = value
}
}
}
</script>

このようにすれば、子コンポーネントで入力した値を親で受け取って表示できます。


複数の値を$emitで渡す方法

$emit では、複数の値を渡すこともできます。

子コンポーネント

this.$emit('update-user', '田中', 30)

親コンポーネント

<ChildComponent @update-user="handleUpdateUser" />
methods: {
handleUpdateUser(name, age) {
console.log(name)
console.log(age)
}
}

ただし、実務では複数の値をバラバラに渡すより、オブジェクトにまとめて渡すほうがわかりやすいことが多いです。

おすすめの書き方

this.$emit('update-user', {
name: '田中',
age: 30
})

親側では次のように受け取れます。

methods: {
handleUpdateUser(user) {
console.log(user.name)
console.log(user.age)
}
}

この書き方のほうが可読性も高く、引数の順番ミスも防ぎやすくなります。

Si quieres conocer otros artículos parecidos a Vue.jsの$emit完全ガイド|親子コンポーネント間で値を渡す方法 puedes visitar la categoría Detakaiseki.

Go up