質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1392閲覧

Vueで使用するdefineEmitsについて、なぜ親コンポーネントでカスタムイベントを受け取って実行する関数に()を付けるとうまく動作しなくなるのでしょうか?

sino3325

総合スコア65

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2023/04/19 12:30

解決したい問題

とても初歩的なことだとは思うのですが、いろいろ調べても解決しなかったのでこちらで質問させていただきます。
以下のコードは「definePropsとdefineEmitsを使って子コンポーネントと親コンポーネントでデータをやり取りし、ボタンを押すとカウントが1ずつ増えるコード」で思い通りに動作しているのですが、親コンポーネントの@clicked="addNumber"の部分を@clicked="addNumber()"に書き換えると、子コンポーネントから受け取る情報が「undefined」になってしまいます。
()を付けるとなぜ子コンポーネントからデータを受け取れなくなってしまうのか知りたいです。
引数に関する初歩的な問題な気がするのですがご教授頂けると幸いです。

ChildComponent.vue

1<!--==================== template ====================--> 2<template> 3 <button @click="startingCustomEvent()">{{ number }}</button> 4</template> 5 6<!--==================== script ====================--> 7<script setup> 8const props = defineProps({ 9 number: { 10 type: Number, 11 required: true 12 } 13}); 14 15const emit = defineEmits(['clicked']); 16const startingCustomEvent = () => { 17 emit('clicked', props.number); 18}; 19</script>

ParentComponent.vue

1<!--==================== template ====================--> 2<template> 3 <p>{{ sum }}</p> 4 <MyCounter :number="1" @clicked="addNumber"/> 5</template> 6 7<!--==================== script ====================--> 8<script setup> 9import { ref } from 'vue'; 10import MyCounter from '../../components/ChildComponent.vue'; 11 12const sum = ref(0); 13const addNumber = (number) => { 14 sum.value += number; 15}; 16</script> 17コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

v-onディレクティブはイベントを制御するディレクティブです。そして、この用例でv-onディレクティブは二通りに用いられている(厳密には別モノ)のでそれを混同しているのだと思います。

1:任意のイベントでメソッドを制御する(イベントハンドリングのインラインメソッドハンドラ)
2:子コンポーネントからの値を受け取る(カスタムイベント)

1:任意のイベントを制御するケース(イベントハンドリング)

@click="startingCustomEvent()はv-on:click="startingCustomEvent()"の省略形で、同一コンポーネントでメソッドを呼び出しています。つまりclickイベントでstartingCustomEvent()というインラインメソッドを呼び出しています。そしてイベントハンドリングの場合はコールバック関数を用いるメソッドイベントハンドラ(v-on:click="startingCustomEventという記述形式で、メソッドの引数からイベントを受け取る)でもインラインメソッドイベントハンドラのいずれでも問題ありません。

2:子コンポーネントからの値を受け取るケース(カスタムイベント)

対する@clickedのclickedは任意に定義されたemitメソッドで用いるためのプロパティ名で、予約されたイベントとは全く無関係です。そしてVue上のカスタムイベントという仕様を用いて制御しますが、その場合はインラインメソッドハンドラは使用できません。

@clicked="addNumber"はv-on:clicked="addNumber"というv-onディレクティブの省略形です。
defineEmitsは任意の子コンポーネントから親コンポーネントに値を送出するためのemitメソッドを生成しており、それを使用する場合、

emit('emitメソッドでキーとなるプロパティ名',送出したい変数)

となります。

そして、emitされたメソッドを親コンポーネントで受け取る場合での親コンポーネント上の記述は

v-on:emitメソッドでキーとなるプロパティ名=親コンポーネントで受け取りに用いるメソッド(コールバック関数)

となります。つまり、質問の条件の通り、子コンポーネントから受け取る場合はカスタムイベントを使うので、メソッドイベントハンドラ、つまり右側の式はコールバック関数でないといけないわけです。

ちなみに

emit('hoge', props.number)

@hoge="addNumber"

とすり替えても動きます。

投稿2023/04/20 02:25

編集2023/04/20 06:41
FKM

総合スコア3640

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sino3325

2023/04/21 04:04

丁寧な解説ありがとうございます! おかげさまで解決しました! 原因はFKMさんのおっしゃる通り、混同しているためでした。 v-onをどっちの役割として使っているのか意識しながらコードを書いていきます。
FKM

2023/04/21 04:14

目の付け所は簡単です。 1のケースならinput、selectなどのフォーム内部品 2のケースならコンポーネント それ以外に付与されることは、まずないです。
guest

0

()を付けるとなぜ子コンポーネントからデータを受け取れなくなってしまうのか知りたいです。

()をつけないと、関数そのものを渡すことになります。
()をつけると、関数を呼び出した結果を渡すことになります。

この場合やりたいのは、クリックした場合どのような処理を行うかでして、それは関数そのものを渡さないと意味がありません。()をつけるかつけないかは重大な差になります。

投稿2023/04/20 02:15

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問