Vue Event Handling: A Complete Guide
We listen for events in an application in order to perform certain actions when they occur. For example, we can display content or fetch data when a button is clicked, a key is pressed, a text input value is changed, and so on. In this article, we're going to learn how to handle events in Vue apps to enable interactivity.
Listening for Events in Vue
To listen for an event, we pass the handler to a v-on
directive attached to an element, for example:
<button v-on:click="handler">Click me</button>
We can also use the @
symbol for a shorter syntax:
<button @click="handler">Click me</button>
There are two types of event handlers in Vue: inline handlers and method handlers.
Inline Event Handlers
To create an inline event handler, we pass inline JavaScript that will be executed when the event is triggered. For example:
<template>
<p>Count: {{ count }}</p>
<button @click="count++">Add 1</button>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
};
</script>
Method Event Handlers
Method event handlers are what we use when we have more complex logic spanning multiple lines of code. We pass the name of a method defined on a Vue component to use it to handle the event.
For example:
<template>
Count: {{ count }}
<br />
<button @click="increment">Add 1</button>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
methods: {
increment() {
this.count++;
if (this.count % 5 === 0) {
alert(`${this.count} is divisible by 5.`);
}
},
},
};
</script>
Calling Methods in Inline Handlers
We can also call a method in an event handler directly. This is useful for passing arguments.
<template>
<p>Count: {{ count }}</p>
<button @click="increment(2)">Add 2</button>
<button @click="increment(3)">Add 3</button>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
methods: {
increment(amount) {
this.count += amount;
if (this.count % 5 === 0) {
alert(`${this.count} is divisible by 5.`);
}
},
},
};
</script>
Accessing Event Arguments in Event Handlers
When the name of a method is passed directly, the DOM event object associated with the event will be passed to the first parameter of the method:
<template>
<button
id="btn-1"
@click="handleClick"
>
Button 1
</button>
</template>
<script>
export default {
methods: {
handleClick(event) {
const target = event.target;
alert(`Button with ID ${target.id} clicked`);
},
},
};
</script>
We can also use an inline arrow function to access this event object:
<template>
<button
id="btn-1"
@click="(event) => handleClick('Peter', event)"
>
Button 1
</button>
</template>
<script>
export default {
methods: {
handleClick(username, event) {
const target = event.target;
alert(
`${username} clicked the button with ID ${target.id}`
);
},
},
};
</script>
Or we could pass the special $event
variable when calling the method from the inline handler:
<template>
<button
id="btn-1"
@click="handleClick('Peter', $event)"
>
Button 1
</button>
</template>
<script>
export default {
methods: {
handleClick(username, event) {
const target = event.target;
alert(
`${username} clicked the button with ID ${target.id}`
);
},
},
};
</script>
Vue Event Modifiers
Vue provides event modifiers that allow us to separate our data logic from event-related logic. For example, the .prevent
event modifier eliminates the need to call event.preventDefault()
in the event handler method:
<template>
<form @submit.prevent="onSubmit">
<input
name="email"
type="email"
placeholder="Email"
/>
<button type="submit">Sign up</button>
</form>
</template>
<script>
export default {
methods: {
onSubmit() {
alert('Signed up successfully.');
},
},
};
</script>
Similarly, the .stop
event modifier removes the need to call event.stopPropagration()
in an event method handler:
<template>
<button
id="outer-btn"
@click="handleOuterButtonClick"
>
Outer button
<button
id="inner-btn"
@click.stop="handleInnerButtonClick"
>
Inner button
</button>
</button>
<p>{{ message1 }}</p>
<p>{{ message2 }}</p>
</template>
<script>
export default {
data() {
return {
message1: '',
message2: '',
};
},
methods: {
handleOuterButtonClick() {
this.message2 = 'Outer button clicked';
},
handleInnerButtonClick() {
this.message1 = 'Inner button clicked.';
},
},
};
</script>
Here is a list of the common event modifiers in Vue:
.stop
.prevent
.self
.capture
.once
.passive
Chained Event Modifiers
We can chain event modifiers in Vue:
<a @click.stop.prevent="handleLink1Click"></a>
<a @click.once.prevent="handleLink2Click"></a>
Key modifiers
It's common to check for specific keys when listening for keyboard events. Vue provides key modifiers for this.
For example, we can listen just for the "Enter" key
<input @keyup.enter="handleSubmit" />
We can use any valid key names exposed through KeyboardEvent.key
as modifiers by converting them to kebab-case:
<input @keyup.page-down="handlePageDown" />
Key Aliases
Vue provides aliases for the most frequently used keys:
.enter
.tab
.delete (captures both "Delete" and "Backspace" keys)
.esc
.space
.up
.down
.left
.right
System Modifier Keys
Applying system key modifiers to key events will only trigger the event when the corresponding modifier key is pressed.
<!-- Ctrl + Enter -->
<input @keyup.ctrl.enter="clearTextField" />
<!-- Ctrl + Click -->
<div @click.ctrl="handleCtrlClick">Do something</div>
Exact Modifier
The .exact
modifier lets us control the exact combination of system modifiers needed to trigger an event:
<!-- this will fire even if Alt or Shift is also pressed -->
<button @click.ctrl="handleClick">Button</button>
<!-- this will only fire when Ctrl and no other keys are pressed -->
<button @click.ctrl.exact="handleCtrlClick">Button</button>
<!-- this will only fire when no system modifiers are pressed -->
<button @click.exact="handleClick">Button</button>
Mouse Button Modifiers
Mouse button event modifiers will only call the event handlers for specific buttons. They are:
.left
.middle
.right
<button @click.left="handleLeftClick">Button</button>
<button @click.middle="handleMiddleClick">Button</button>
<button @click.right="handleRightClick">Button</button>
Conclusion
We can listen for events in Vue by passing inline code or a method handler to the v-on
directive for the event. We can apply various modifiers to an event to further customize event trigger conditions.