目的と背景
久しぶりにVue3でフロントエンド開発をした時にemitってどうやって使うんだっけ?と調べたところ、TypeScriptで書かれた記事ばっかりだったので、JavaScriptベースだとこうだよというのを残しておこうと思った
そもそもemitってなに?
子コンポーネントから親コンポーネントの操作を実行するための仕組み。
例えば、親コンポーネントが持っている変数を子コンポーネント内で変更するような時に使う。
store使えばよくない?
piniaなどのstoreを使えばコンポーネントの階層に関係なく状態を参照/更新できるので、emit使わなくてもよいが、個人的には単に親コンポーネントが参照し、単一の子コンポーネントが更新をするような時はstoreでやるほどではないなという感覚。
単一の子コンポーネントが更新を担当し、親コンポーネントが別の子コンポーネントにその状態を渡すような場面ではstoreのがいいかなと思う。
本題
今回はファイルの表示画面でリスト表示とギャラリー表示どちらの状態にあるかを表す「type」を子コンポーネント上の要素のクリックによって切り替える場面を考える。
まず、親コンポーネントで参照する変数とメソッドを定義して、子コンポーネントに渡す
<template>
<ChileComponent @changeType="changeType"/>
{{ type }}
</template>
<script setup>
const type = ref('list');
const changeType = (newType) =>{
type.value = newType;
};
</script>
子コンポーネントではdefineEmitsして、emitとして使えるように定義をしてからそれを呼び出す
<template>
<div>
<div @click="emits('changeType','list')">リスト</div>
<div @click="emits('changeType','gallery')">ギャラリー</div>
</div>
</template>
<script setup>
const emits = defineEmits(['changeType']);
</script>
上記で正しく子コンポーネントから親コンポーネントの操作をすることができた。