【Vue 2】イベントハンドリング
v-on
基本構文
Vue.js では、v-on
を用いることでメソッドをイベントリスナーとしてバインドします。
v-on
は@
と省略することができます。
<!-- 省略なし -->
<button v-on:click="count">Count Up</button>
<!-- 省略あり -->
<button @click="count">Count Up</button>
data: {
counter: 1
},
methods: {
count() {
counter++
}
}
イベントオブジェクト
メソッドに引数を設定することで、イベントオブジェクトを取得できます。 バインド時は、メソッド名のみ指定します。
methods: {
onClick(event) {
console.log(event) //イベントオブジェクトの表示
}
}
<button @click="onClick">click</button>
メソッドにイベントハンドラー以外の引数を使用する場合は、$event
をバインド時に指定します。
methods: {
onClick(event, arg) {
console.log(event, arg)
}
}
<button @click="onClick($event, 'data')">click</button>
イベント修飾子
イベント修飾子は、イベントを制御するためのもので以下のようなものがあります。
stop
子要素から親要素へのイベントの伝搬を止めます。これはstopPropagetion()
に該当します。
<div @click="count">
<div @click.stop="count">
</div>
</div>
stopなし
count: 0
stopあり
count: 0
prevent
要素のデフォルトアクションを抑止します。これはpreventDefault()
に該当します。
例えば<a>
ではhref
の処理が実行されなくなります。
<a href="javascript:alert('href action')" @click.prevent="onClick">action</a>
methods: {
onClick() {
alert('click action')
}
}
capture
イベントの伝搬による発火順序が逆順になります。 つまり子 → 親から親 → 子の順に変わります。
これはaddEventListener()
のcapture
に該当します。
<div @click.capture="onClick1">
<div @click="onClick2">
</div>
</div>
methods: {
onClick1() {
alert('click 1')
},
onClick2() {
alert('click 2')
}
}
captureなし
captureあり
self
イベントが要素自身にアクションした場合のみ発火するようになります。
子要素にアクションした時に違いがわかると思います。
<div @click.self="onClick">
<div>
</div>
</div>
methods: {
onClick() {
alert('clicked')
}
}
selfなし
selfあり
once
イベントの発火を 1 回に制限します。
これはaddEventListener()
のonce
に該当します。
<button @click.once="count">click</button>
count: 0
passive
addEventListener()
のpassive
に該当します。
Scroll Jank の解決策などで用いられるようです。
イベント一覧
click, dblclick
クリック、ダブルクリック時に発火するイベントです。
<button @click="count">click</button>
<button @dblclick="count">double click</button>
count: 0
keydown, keyup
キーを押した時、離した時に発火するイベントです。
<input @keydown="count">
<input @keyup="count">
修飾子として、キーコードまたは以下のキー名を指定することで任意のキーだけでイベントを発火させることができます。 Vue 3 ではキーコードの指定は非推奨とされており、ケバブケースによるキー名で指定することが推奨されています。
キー名 | 説明 |
---|---|
enter | Enter キー |
tab | Tab キー |
ctrl | Ctrl キー |
shift | Shift キー |
delete | Delete キー |
esc | Esc キー |
space | スペースキー |
meta | メタキー |
up | ↑ キー |
right | → キー |
down | ↓ キー |
left | ← キー |
<input @keydown.enter="count">
<input @keydown.13="count">
count: 0
キーのイベントにはkeypress
がありますが、JavaScript として現在非推奨とされています。
参考:MDN
focus, blur
フォーカス時、フォーカスが外れた時に発火するイベントです。
<input @focus="onFocus" @blur="onBlur">
data: {
status: ''
},
methods: {
onFocus() {
this.status = 'focus'
},
onBlur() {
this.status = 'blur'
}
}
状態:
change
フォーカスされてからフォーカスが外れるまでの間に、値が変化していれば発火するイベントです。
<input @change="onChange" @focus="onFocus" >
data: {
status: ''
},
methods: {
onChange() {
this.status = 'changed'
},
onFocus() {
this.status = 'not change'
}
}
状態:
mouseover, mouseout
マウスカーソルを当てた時、外した時に発火するイベントです。
<div @mouseover="onMouseover" @mouseout="onMouseout"></div>
data: {
status: 'mouse out'
},
methods: {
onMouseover() {
this.status = 'mouse over'
},
onMouseout() {
this.status = 'mouse out'
}
}
mouse out
mouseenter, mouseleave
mouseover
、mouseout
と同じくマウスカーソルを当てた時、外した時に発火するイベントです。
<div @mouseenter="onMouseenter" @mouseleave="onMouseleave"></div>
前者との違いは、イベントの伝搬にあります。 まずはプレビューでイベント発火数の違いを確認してみてください。
[parent] over: 0, out: 0, enter: 0, leave: 0
[child] over: 0, out: 0, enter: 0, leave: 0
mouseover
、mouseout
は子要素のイベントが親要素に伝搬します。
つまり、子要素のmouseover
発火時に親要素のmouseover
も発火します。
一方、mouseenter
、mouseleave
ではイベントの伝搬は発生しません。
mousedown, mouseup
マウスのボタンを押した時、離した時に発火するイベントです。
修飾子としてleft
、right
、middle
があり、それぞれ左クリック、右クリック、ホイールクリックにイベントを制限することができます。
<div @mousedown="count"></div>
<div @mouseup="count"></div>
<div @mousedown.left="count"></div>
down: 0, up: 0
left: 0
right: 0
middle: 0
dragstart, dragend, drag
draggable
な要素に対して、ドラッグ開始時、ドラッグ終了時、ドラッグ中に発火するイベントになります。
<div draggable @dragstart="onDragStart" @dragend="onDragEnd" @drag="onDrag"></div>
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
}
}
}
status: end, position (0, 0)
dragover, dragleave
ドラッグされる側のイベントで、ドラッグしている要素を当てた時、外した時に発火します。
<div @dragenter="onDragEnter" @dragleave="onDragLeave"></div>
data: {
status: 'leave',
},
methods: {
onDragEnter() {
this.status = "enter"
},
onDragLeave() {
this.status = "leave"
}
}
status: leave
dragover, drop
ドラックされる側のイベントで、ドラッグしている要素が当てられている間、ドラッグしている要素が自身の要素内で離された時に発火します。
この 2 つのイベントは、ドラッグ&ドロップを実装する上で使用しますが、2 つの注意点があります。
1 つ目は、dragover
にprevent
修飾子を付与することです。
これをしなければdrop
が動作しません。
2 つ目は、drop
にstop
修飾子を付与することです。
これをしなければイベントが伝搬し、親のドロップイベントが発火してしまいます。
例えばファイルをドロップする場合に、ブラウザでプレビューが表示されるといったことが発生します。
<div @dragover.prevent="" @drop.stop="onDrop"></div>
data: {
counter: 0
},
methods: {
onDrop() {
this.counter++
}
}
drop count: 0
scroll
スクロール時に発火するイベントです。
<div @scroll="onScroll">
<div></div>
</div>
data: {
y: 0
},
methods: {
onScroll(event) {
this.y = event.target.scrollTop
}
}
0
submit
<form>
に対し、submit された時に発火するイベントです。
submit
を使用する際は、必ずprevent
修飾子を付与するようにしてください。
<form @submit.prevent="submit">
<input type="text" v-model="val"><br>
<input type="submit" value="submit">
</form>
data: {
val: ''
},
methods: {
submit() {
alert('submit')
}
}