honapon
@honapon

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【チュートリアル】Vue.jsのPropsを用いたクリックイベント

解決したいこと

Vue.js3のPropsを用いたクリックイベントの実装を練習として行っています。
内容はとてもシンプルなもので、「ボタンをクリックするとボタンの文字が変わる」というものなのですが、イベント発生前の文章「発火前」をどこに記入(初期化?)すると良いのか分からず困っています。
下記のコードで現在ボタンが常に「発火済」と表示されています。
Propsでは親から子にプロパティ・値を渡すとありますが、それ以前の状態について子・親のどちらにどのように書くべきなのか悩んでいます。

ご教授頂けると大変助かります。

Message.Vue(子)

<script setup>
const props = defineProps({
 msg:String
})
</script>

<template>
  <h1>練習</h1>
<button @click = msg >{{ msg }}</button>
</template>

App.Vue(親)

<script setup>
import Counter from './Message.vue'
import { ref }from 'vue'
const changedMessage = ref("発火済")
</script>

<template>
<Counter :msg = "changedMessage" />
</template>

0

2Answer

もしかしたら解決済みかもしれませんが・・・

Propsでは親から子にプロパティ・値を渡すとありますが、それ以前の状態について子・親のどちらにどのように書くべきなのか悩んでいます。

propsで渡すということは親でデータを管理してあげるのが良いかと思います。
子で管理するものはない、または「値が設定されていない時に表示されるデフォルト値」のみを管理するのが理想です。(今回この話は省略します)

その上で・・・初期値というのは一番最初の値ですので

const changedMessage = ref("発火前")

ここがこのようになります。
その上で・・・今回やりたいことは「クリックしたらテキストを変更する」だと思いますので、クリックのイベントを作ってあげる必要があります。

まずは親ですが

App.vue
<script setup>
  import Message from './Message.vue'
  import { ref }from 'vue'
  const changedMessage = ref("発火前")
  const hanldeClick = () => {
    changedMessage.value = '発火済'
  }
</script>

<template>
  <Message :msg="changedMessage" @click="hanldeClick" />
</template>

このように

  • propsでメッセージを渡す
  • emitでイベントを渡す

という情報を子のコンポーネントへ渡してあげる必要があります。
hanldeClickを実行すると

    changedMessage.value = '発火済'

としているので、changedMessageの中身が発火前から発火済に切り替わります。

あとはこれを子で使えるようにするだけです。(普段TypeScriptで書くのでJavaScriptでの書き方が分からず、間違ってるかもしれません)
https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits

Message.vue
<script setup>
const props = defineProps({
 msg:String
})
const emit = defineEmits(['click'])
</script>

<template>
  <h1>練習</h1>
  <button @click="() => emit('click')" >{{ msg }}</button>
</template>

こうするとbuttonをクリックするとMessage.vueに渡ってきた@clickが実行されるようになり、
App.vueのhanldeClickが実行されるので文字が切り替わるようになります。

1Like

Comments

  1. @honapon

    Questioner

    解説とコードの見本も作成して頂き、ありがとうございます。希望通り動作しました。1つ1つ順に説明して頂いたことで、Propsとemitの内容だけでなく、順を追って考えてコードを書いていくということがとても大切であると感じました。Vue3の解説はまだまだ少ない中、教えて頂いたことに感謝しております。基本文としてこちらを参考にしながらこれからも練習していきたいと思います。

実行環境が整ってないので実証はちょっとできてないですが、これでいけるんじゃないでしょうかね…?

Message.Vue
<script setup>
const props = defineProps({
 msg: {
  type: String,
  required: false,
  defailt: function() {// デフォルト値の設定はデフォルト値を返す関数として書く必要があります
   return 'デフォルト値';
  }// ちなみに親コンポーネントに値を持たせる場合、required: true にして、default関数を省くこともできます。
 }
})
const changeMessage = function() {
 this.$emit(changeMessage)// 多分親コンポーネントに値を管轄させたいと思うので、親コンポーネントに頼んで値を変えてもらいます
};
</script>

<template>
  <h1>練習</h1>
<button @click = changeMessage >{{ msg }}</button>
</template>

App.Vue
<script setup>
import Counter from './Message.vue'
// 親コンポーネントに値を持たせる場合、このあたりで msg = 'デフォルト値'; 等とします。
const changeMessage = function() {// 親コンポーネントが子コンポーネントから頼まれて発火させる関数です
 msg = '発火済み'
}
</script>

<template>
<Counter :msg = msg /><!-- 親コンポーネントと子コンポーネントで同名の変数を使ってるので、混同しないようにご注意 -->
</template>

0Like

Comments

  1. @honapon

    Questioner

    丁寧な見本と解説をありがとうございます!納得し、やっとすっきり理解が出来ました。Vueのチュートリアルでシンプルな実装の練習しかしていなかったので、this.$emitの使い方、propsのプロパティのfalseの部分などとても勉強になります。今回のコード以外でも是非参考にさせて頂きたいと思います。

Your answer might help someone💌