Vue イベント修飾子
1. イベント修飾子とは
Vue の イベント修飾子(Event Modifiers) は、イベントが メソッド(Methods) を実行するトリガー条件を調整し、より効率的かつ簡潔にイベントを処理することを可能にします。
イベント修飾子は Vue の v-on ディレクティブと一緒に使用され、例えば以下のようなケースで役立ちます:
- HTML フォームのデフォルトの送信(
submit)挙動を抑制する (v-on:submit.prevent) - ページ読み込み後、イベントを一度だけ実行するように設定する (
v-on:click.once) - メソッドを実行するための特定のキーボードキーを指定する (
v-on:keyup.enter)
2. v-on ディレクティブの修飾方法
イベント修飾子は、イベントに対する反応(リアクション)をより詳細に定義するために使用されます。
まず、以前学んだようにタグをイベントに接続します:<button v-on:click="createAlert">アラートを作成</button>
ここで、ボタンのクリックイベントを「ページ読み込み後に一度だけ」実行されるように限定したい場合、.once 修飾子を次のように追加します:<button v-on:click.once="createAlert">アラートを作成</button>
2.1 実装例:.once 修飾子
.once 修飾子を使用することで、最初にクリックしたときだけメソッドが実行されます。
<div id="app">
<p>ボタンをクリックしてアラートを表示(一度だけ動作します):</p>
<button v-on:click.once="createAlert">アラート作成</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
methods: {
createAlert() {
alert("ボタンのクリックによりアラートが作成されました")
}
}
})
app.mount('#app')
</script>注釈: 修飾子を使わずにメソッド内でイベントを処理することも可能ですが、イベント修飾子を使用することでコードがはるかにシンプルかつ直感的になります。
3. さまざまな v-on 修飾子
イベント修飾子は、キーボードイベントやマウスクリックイベントなど、さまざまな状況で使用できます。また、複数の修飾子を組み合わせて使用することも可能です。
なお、.once 修飾子はキーボードイベントとマウスクリックイベントの両方で使用できます。
4. キーボードイベント修飾子
キーボードイベントには、keydown、keypress、keyup の3つのタイプがあります。
各イベントタイプにおいて、どのキーを監視するかを具体的に指定できます。代表的なものに .space、.enter、.w、.up などがあります。
特定のキーの値を確認したい場合は、console.log(event.key) を使用してコンソールやWebページに出力してみるのが良いでしょう。
4.1 実装例:キー入力の検知
keydown イベントによって getKey メソッドが実行され、イベントオブジェクトから取得した key の値を表示します。
// データとメソッドの定義例
data() {
return {
keyValue: ''
}
},
methods: {
getKey(evt) {
this.keyValue = evt.key
console.log(evt.key)
}
}また、マウスボタンやキー入力が、システム修飾キー(System Modifier Keys) である .alt、.ctrl、.shift、.meta と組み合わされたときだけイベントを発生させることも可能です。
※ .meta は Windows の場合は Windows キー、Mac の場合は Command キーを指します。
4.2 キー修飾子の一覧
| 修飾子 | 詳細 |
|---|---|
.[Vue key alias] | よく使われるキーにはエイリアスがあります:.enter, .tab, .delete, .esc, .space, .up, .down, .left, .right |
.[letter] | キーを押した際に出力される文字を指定します。例:.s 修飾子で 'S' キーを監視 |
.[system modifier key] | .alt, .ctrl, .shift, .meta。これらは他のキーやマウスクリックと組み合わせて使用できます。 |
4.3 実装例:特定のキー入力で実行
<textarea> 内で 's' キーが押されたときだけアラートを表示します。
<div id="app">
<p>'s' キーを押してみてください:</p>
<textarea v-on:keyup.s="createAlert"></textarea>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
methods: {
createAlert() {
alert("'S' キーが押されました!")
}
}
})
app.mount('#app')
</script>5. キーボードイベント修飾子の組み合わせ
修飾子を連結させることで、「複数のアクションが同時に行われたときだけ」メソッドを呼び出すように設定できます。
5.1 実装例:Ctrl + S の検知
ctrl と s が同時に押されたときだけアクションを実行します。
<div id="app">
<p>Ctrl + S キーを押してみてください:</p>
<textarea v-on:keydown.ctrl.s="createAlert"></textarea>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
methods: {
createAlert() {
alert("'Ctrl' と 'S' が同時に押されました!")
}
}
})
app.mount('#app')
</script>6. マウスボタン修飾子
マウスのクリックに反応させるには v-on:click を使用しますが、特定のボタン(左、中央、右)を限定するには .left、.center、.right 修飾子を使用します。
6.1 実装例:右クリックによる背景変更
<div> 要素を右クリックしたときに背景色を変更します。
<div id="app">
<div v-on:click.right="changeColor"
v-bind:style="{backgroundColor:'hsl('+bgColor+',80%,80%)'}">
<p>ここでマウスの右ボタンを押してください。</p>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
bgColor: 0
}
},
methods: {
changeColor() {
this.bgColor += 50
}
}
})
app.mount('#app')
</script>7. .prevent 修飾子の活用
右クリック時にデフォルトで表示される コンテキストメニュー(ドロップダウンメニュー) を防ぎつつ、独自の処理を行いたい場合は、.right に .prevent を組み合わせて使用します。
7.1 実装例:デフォルトメニューの抑制
右クリックで背景色を変更しつつ、ブラウザのメニュー表示を禁止します。
<div id="app">
<div v-on:click.right.prevent="changeColor"
v-bind:style="{backgroundColor:'hsl('+bgColor+',80%,80%)'}">
<p>ここで右クリック。メニューは表示されません。</p>
</div>
</div> プロの視点: メソッド内で event.preventDefault() を記述することでも同様の処理は可能ですが、Vue の .prevent 修飾子を使用することで、ロジック(JavaScript)とUIの挙動制御が分離され、コードの可読性とメンテナンス性が向上します。
7.2 実装例:Shift + 左クリック
他の修飾子との組み合わせも自由自在です。
<div id="app">
<p>'Shift' キーを押しながら左クリックしてください:</p>
<img v-on:click.left.shift="changeImg" v-bind:src="imgUrl">
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
imgUrlIndex: 0,
imgUrl: 'img_tiger_square.jpeg',
images: [
'img_tiger_square.jpeg',
'img_moose_square.jpeg',
'img_kangaroo_square.jpeg'
]
}
},
methods: {
changeImg() {
this.imgUrlIndex++
if(this.imgUrlIndex >= 3){
this.imgUrlIndex = 0
}
this.imgUrl = this.images[this.imgUrlIndex]
}
}
})
app.mount('#app')
</script>