vue.svg

【Vue 2】イベントハンドリング

Vue 2

v-on

基本構文

Vue.js では、v-onを用いることでメソッドをイベントリスナーとしてバインドします。 v-on@と省略することができます。

HTML
<!-- 省略なし -->
<button v-on:click="count">Count Up</button>
<!-- 省略あり -->
<button @click="count">Count Up</button>
JavaScript
data: {
  counter: 1
},
methods: {
  count() {
    counter++
  }
}

イベントオブジェクト

メソッドに引数を設定することで、イベントオブジェクトを取得できます。 バインド時は、メソッド名のみ指定します。

JavaScript
methods: {
  onClick(event) {
    console.log(event)  //イベントオブジェクトの表示
  }
}
HTML
<button @click="onClick">click</button>

メソッドにイベントハンドラー以外の引数を使用する場合は、$eventをバインド時に指定します。

JavaScript
methods: {
  onClick(event, arg) {
    console.log(event, arg)
  }
}
HTML
<button @click="onClick($event, 'data')">click</button>

イベント修飾子

イベント修飾子は、イベントを制御するためのもので以下のようなものがあります。

stop

子要素から親要素へのイベントの伝搬を止めます。これはstopPropagetion()に該当します。

HTML
<div @click="count">
  <div @click.stop="count">
  </div>
</div>

stopなし

parent
child

count: 0


stopあり

parent
child

count: 0

prevent

要素のデフォルトアクションを抑止します。これはpreventDefault()に該当します。

例えば<a>ではhrefの処理が実行されなくなります。

HTML
<a href="javascript:alert('href action')" @click.prevent="onClick">action</a>
JavaScript
methods: {
  onClick() {
    alert('click action')
  }
}

capture

イベントの伝搬による発火順序が逆順になります。 つまり子 → 親から親 → 子の順に変わります。

これはaddEventListener()captureに該当します。

HTML
<div @click.capture="onClick1">
  <div @click="onClick2">
  </div>
</div>
JavaScript
methods: {
  onClick1() {
    alert('click 1')
  },
  onClick2() {
    alert('click 2')
  }
}

captureなし

parent
child

captureあり

parent
child

self

イベントが要素自身にアクションした場合のみ発火するようになります。

子要素にアクションした時に違いがわかると思います。

HTML
<div @click.self="onClick">
  <div>
  </div>
</div>
JavaScript
methods: {
  onClick() {
    alert('clicked')
  }
}

selfなし

parent
child

selfあり

parent
child

once

イベントの発火を 1 回に制限します。 これはaddEventListener()onceに該当します。

HTML
<button @click.once="count">click</button>

count: 0

passive

addEventListener()passiveに該当します。

Scroll Jank の解決策などで用いられるようです。

イベント一覧

click, dblclick

クリック、ダブルクリック時に発火するイベントです。

HTML
<button @click="count">click</button>
<button @dblclick="count">double click</button>

count: 0

keydown, keyup

キーを押した時、離した時に発火するイベントです。

HTML
<input @keydown="count">
<input @keyup="count">

修飾子として、キーコードまたは以下のキー名を指定することで任意のキーだけでイベントを発火させることができます。 Vue 3 ではキーコードの指定は非推奨とされており、ケバブケースによるキー名で指定することが推奨されています。

キー名説明
enterEnter キー
tabTab キー
ctrlCtrl キー
shiftShift キー
deleteDelete キー
escEsc キー
spaceスペースキー
metaメタキー
up↑ キー
right→ キー
down↓ キー
left← キー
HTML
<input @keydown.enter="count">
<input @keydown.13="count">






count: 0

キーのイベントにはkeypressがありますが、JavaScript として現在非推奨とされています。

参考:MDN

focus, blur

フォーカス時、フォーカスが外れた時に発火するイベントです。

HTML
<input @focus="onFocus" @blur="onBlur">
JavaScript
data: {
  status: ''
},
methods: {
  onFocus() {
    this.status = 'focus'
  },
  onBlur() {
    this.status = 'blur'
  }
}

状態:

change

フォーカスされてからフォーカスが外れるまでの間に、値が変化していれば発火するイベントです。

HTML
<input @change="onChange" @focus="onFocus" >
JavaScript
data: {
  status: ''
},
methods: {
  onChange() {
    this.status = 'changed'
  },
  onFocus() {
    this.status = 'not change'
  }
}

状態:

mouseover, mouseout

マウスカーソルを当てた時、外した時に発火するイベントです。

HTML
<div @mouseover="onMouseover" @mouseout="onMouseout"></div>
JavaScript
data: {
  status: 'mouse out'
},
methods: {
  onMouseover() {
    this.status = 'mouse over'
  },
  onMouseout() {
    this.status = 'mouse out'
  }
}
Prease mouse over.

mouse out

mouseenter, mouseleave

mouseovermouseoutと同じくマウスカーソルを当てた時、外した時に発火するイベントです。

HTML
<div @mouseenter="onMouseenter" @mouseleave="onMouseleave"></div>

前者との違いは、イベントの伝搬にあります。 まずはプレビューでイベント発火数の違いを確認してみてください。

parent
child

[parent] over: 0, out: 0, enter: 0, leave: 0

[child] over: 0, out: 0, enter: 0, leave: 0

mouseovermouseoutは子要素のイベントが親要素に伝搬します。 つまり、子要素のmouseover発火時に親要素のmouseoverも発火します。

一方、mouseentermouseleaveではイベントの伝搬は発生しません。

mousedown, mouseup

マウスのボタンを押した時、離した時に発火するイベントです。

修飾子としてleftrightmiddleがあり、それぞれ左クリック、右クリック、ホイールクリックにイベントを制限することができます。

HTML
<div @mousedown="count"></div>
<div @mouseup="count"></div>
<div @mousedown.left="count"></div>
normal

down: 0, up: 0


left

left: 0


right

right: 0


middle

middle: 0

dragstart, dragend, drag

draggableな要素に対して、ドラッグ開始時、ドラッグ終了時、ドラッグ中に発火するイベントになります。

HTML
<div draggable @dragstart="onDragStart" @dragend="onDragEnd" @drag="onDrag"></div>
JavaScript
data: {
  status: 'end',
  position: {
    x: 0,
    y: 0
  }
},
methods: {
  onDragStart() {
    this.status = "start"
  },
  onDragEnd() {
    this.status = "end"
  },
  onDrag(event) {
    this.position {
      x: event.x,
      y: event.y
    }
  }
}
drag

status: end, position (0, 0)

dragover, dragleave

ドラッグされる側のイベントで、ドラッグしている要素を当てた時、外した時に発火します。

HTML
<div @dragenter="onDragEnter" @dragleave="onDragLeave"></div>
JavaScript
data: {
  status: 'leave',
},
methods: {
  onDragEnter() {
    this.status = "enter"
  },
  onDragLeave() {
    this.status = "leave"
  }
}
drag
target

status: leave

dragover, drop

ドラックされる側のイベントで、ドラッグしている要素が当てられている間、ドラッグしている要素が自身の要素内で離された時に発火します。

この 2 つのイベントは、ドラッグ&ドロップを実装する上で使用しますが、2 つの注意点があります。

1 つ目は、dragoverprevent修飾子を付与することです。 これをしなければdropが動作しません。

2 つ目は、dropstop修飾子を付与することです。 これをしなければイベントが伝搬し、親のドロップイベントが発火してしまいます。 例えばファイルをドロップする場合に、ブラウザでプレビューが表示されるといったことが発生します。

HTML
<div @dragover.prevent="" @drop.stop="onDrop"></div>
JavaScript
data: {
  counter: 0
},
methods: {
  onDrop() {
    this.counter++
  }
}
drag
target

drop count: 0

scroll

スクロール時に発火するイベントです。

HTML
<div @scroll="onScroll">
  <div></div>
</div>
JavaScript
data: {
  y: 0
},
methods: {
  onScroll(event) {
    this.y = event.target.scrollTop
  }
}

0

submit

<form>に対し、submit された時に発火するイベントです。

submitを使用する際は、必ずprevent修飾子を付与するようにしてください。

HTML
<form @submit.prevent="submit">
  <input type="text" v-model="val"><br>
  <input type="submit" value="submit">
</form>
JavaScript
data: {
  val: ''
},
methods: {
  submit() {
    alert('submit')
  }
}