vueのクリックイベントで、子のイベントを親に渡す方法。


Vueのクリックイベントで子のイベントを親に引き継ぐ方法。

(子テンプレートのボタンをクリックしたときに、親テンプレートで定義しているメソッドを実行する方法)

設定手順

子:①クリックイベントを設定 @click=$emit('イベント名')
  ↓
親:②子のイベントを受け取る (子のタグ内で設定したイベント名)
  ↓
親:③methodsに処理を記述

・子から親にイベントを引き継ぐ。
$emit  子から親へのデータ/イベント受け渡し
@click  v-on:click の省略形


記述例

・用意するファイルは2つ
親:parent.vue
子:TmpBtn.vue

・実現したいこと
親で呼び出した小テンプレートのボタンをクリックしたときに、親テンプレートで設定してあるメソッドを実行する。

(子)TmpBtn.vue
<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    //①クリックイベントを設定
    @click="$emit('child-click')"
    >
    ボタン
    </v-btn>
</template>

子テンプレートのボタンがクリックされると、child-clickというイベントを親に渡す。

(親)parent.vue
<template>
  <v-app>
    <TmpBtn
  <!--②子のイベントを受け取る-->
    @child-click="BtnClicked(hello)"
    />
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  components:{
    TmpBtn
  },
  data(){
    return{
      hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    //③methodsに処理を記述
    BtnClicked(a){
      console.log(a)
    }
  }
}
</script>

子テンプレートのボタンがクリックされたら、BtnClickedメソッドを実行する。

▼実行例

子テンプレートのボタンクリックで、親テンプレートで設定したイベントの発火に成功。


$emitしないとどうなるか

$emitしない場合、イベント設定は2種類考えられる。

  1. 子テンプレートにclickイベントとメソッドを記述 → OK
  2. 親テンプレートにclickイベントとメソッドを記述 → NG

上記の場合、正常に作動するのは1のみ
2の親テンプレートで呼び出した子テンプレートタグにclickイベントを設定しても動作しない。


子テンプレートに記述する場合

<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    @click="ChildClicked(child)"
    >
    ボタン
    </v-btn>
</template>

<script>
export default {
  methods:{
    ChildClicked(a){
      console.log(a)
    }
  },
  data(){
    return{
      child:"子テンプレートのボタンがクリックされました"
    }
  }
}
</script>

正常に作動。

親テンプレートに記述する場合

(親)parent.vue
<template>
  <v-app>
    <TmpBtn
    :bind="text"
    <!--子テンプレートを呼び出し、クリックイベントを設定-->
    @click="BtnClicked(hello)"
    />
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  components:{
    TmpBtn
  },
  data(){
    return{
     hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    BtnClicked(a){
      console.log(a)
    }
  }
}
</script>

反応なし。。

親テンプレートに記述したメソッドを実行する場合は下記2パターンで検討する必要がある。

①子からイベントを引き継ぐ
②親テンプレート内にボタンを作成したクリックイベントを設定する


イベント情報を渡す ($event)

変数$eventを使うことで、クリックした画面上の位置情報などを渡すことができる。

(子)TmpBtn.vue
<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    <!--clickイベントの引数で$eventを渡す-->
    @click="$emit('chiled-clicked', $event)"
    >
    ボタン
    </v-btn>
</template>
(親)parent.vue
<template>
  <v-app>
    <TmpBtn
    <!--子テンプレのイベントを受け取り、メソッドを実行-->
    @chiled-clicked="BtnClicked(hello, $event)"
    />
    <br>
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  name: "Parent",
  components:{
    TmpBtn
  },
  data(){
    return{
      hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    //第2引数に$eventを渡す
    BtnClicked(a, b){
      console.log(a)
      console.log(b)
    }
  }
}

▼実行結果

$eventの中身
MouseEvent {isTrusted: true, screenX: 77, screenY: 151, clientX: 77, clientY: 17, …}
isTrusted: true
screenX: 77
screenY: 151
clientX: 77
clientY: 17
ctrlKey: false
shiftKey: false
altKey: false
metaKey: false
button: 0
buttons: 0
relatedTarget: null
pageX: 77
pageY: 17
x: 77
y: 17
offsetX: 61
offsetY: 10
movementX: 0
movementY: 0
fromElement: null
toElement: span.v-btn__content
layerX: 61
layerY: 9
view: Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
detail: 1
sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
which: 1
type: "click"
target: span.v-btn__content
currentTarget: null
eventPhase: 0
bubbles: true
cancelable: true
defaultPrevented: false
composed: true
timeStamp: 132300.8249999839
srcElement: span.v-btn__content
returnValue: true
cancelBubble: false
path: (8) [span.v-btn__content, button.v-btn.v-btn--rounded.theme--light.elevation-2.v-size--default, div.v-application--wrap, div#app.v-application.v-application--is-ltr.theme--light, body, html, document, Window]
__proto__: MouseEvent



$event内の特定のデータが欲しい場合はプロパティを指定する。

  methods:{
    BtnClicked(a, b){
      console.log(b.type)
    }
  }

//出力
//click