※ 当ブログ「日々是事始め(コレコト)」はプロモーションを含みます。
コンポーネントを部品に分けると、次は「部品どうしをどうつなぐか」が問題になります。親から子へデータを渡したい、子で起きたクリックを親で受け取りたい、子の中身を親から差し替えたい——これを担うのが props・emits・slots の3つです。最初は似ていて混乱しましたが、向きと役割で整理すると一気にスッキリしました。
※ 学習用に調べた内容を個人的にまとめたものです。文章は AI の補助を受けて作成しています。
3つの役割を「向き」で覚える
| 機能 | 向き | 役割 |
|---|---|---|
| props | 親 → 子 | 親から子へデータを渡す |
| emits | 子 → 親 | 子から親へイベントを通知する |
| slots | 親 → 子 | 親から子へ表示内容(HTML)を差し込む |
「データを渡す=props」「イベントを返す=emits」「見た目を差し込む=slots」。この対応だけ押さえれば十分です。
props:親から子へデータを渡す
子コンポーネント側で defineProps を使って「受け取る値」を宣言します。<script setup> なら型引数で型も一緒に決められます。
<!-- 子: MyButton.vue -->
<script setup lang="ts">
const props = defineProps<{
label: string
disabled?: boolean
}>()
</script>
<template>
<button :disabled="props.disabled">{{ props.label }}</button>
</template>
<!-- 親から使う -->
<MyButton label="保存する" :disabled="isSaving" />
文字列はそのまま label="保存する"、変数や真偽値は :disabled="isSaving" のように :(v-bind)を付けて渡します。
emits:子から親へイベントを通知する
子で起きた出来事(クリックなど)を親に知らせるのが emits。子で defineEmits を宣言し、emit('イベント名') で発火します。
<!-- 子: MyButton.vue -->
<script setup lang="ts">
const emit = defineEmits<{
click: []
}>()
</script>
<template>
<button @click="emit('click')">押す</button>
</template>
<!-- 親で受け取る -->
<MyButton @click="onClick" />
親は @click="onClick" で子のイベントを受け取ります。値を一緒に渡したいときは emit('submit', 入力値) のように第2引数に乗せます。
slots:親から子へ表示を差し込む
「枠は子が用意して、中身は親が決めたい」ときに使うのが slots。子に <slot /> という差し込み口を置きます。
<!-- 子: CardBox.vue -->
<template>
<div class="card">
<slot /> <!-- ここに親の中身が入る -->
</div>
</template>
<!-- 親から使う -->
<CardBox>
<h2>お知らせ</h2>
<p>好きなHTMLを差し込めます</p>
</CardBox>
枠(カードの見た目)は使い回しつつ、中身だけ場所ごとに変えられます。見出し・本文など複数の差し込み口が欲しいときは「名前付きスロット」も使えます。
最重要の落とし穴:props は子で書き換えない
Vue のデータの流れは「親 → 子」の一方向が原則です。子が受け取った props を子の中で直接書き換えるのは NG。値を変えたいときは、emits で親に「変えてほしい」と通知し、実際の変更は親が行うのが基本形です。
- ❌ 子で
props.value = ...と直接書き換える - ✅ 子で
emit('update', 新しい値)→ 親が状態を更新する
入力欄でよく使う v-model は、この「props で渡して emits で返す」パターンをまとめた便利な仕組みです。まずは一方向の流れを崩さない、と覚えておけば大きな事故は防げます。
もっと体系的に学ぶなら(書籍)
この記事はシリーズの一部です。TypeScript前提で Composition API・Pinia・Vue Router・テストまで一冊で体系的に学びたい方には、内容がそのまま重なる次の本がおすすめです。
PR
📕 紙の本
Vue 3 フロントエンド開発の教科書 [ WINGSプロジェクト 齊藤 新三 ] 価格:3960円 |
📱 電子書籍版
Vue 3 フロントエンド開発の教科書 【電子書籍】[ WINGSプロジェクト 齊藤新三【著】 ] 価格:3960円 |
次に読む



