Event Handling
Vue.js Development
Event Handling
Event handling in Vue goes beyond simple click listeners. Vue provides a comprehensive event system that includes DOM event handling with modifiers, custom event emission from child components, and a clean syntax for common patterns like preventing default behavior, stopping propagation, and debouncing. The v-on directive (shorthand @) is the primary tool for listening to events, while $emit enables components to communicate upward to their parents. Mastering Vue's event system is essential for building interactive, component-based applications.
Inline and Method Handlers
Vue supports both inline expressions and method references as event handlers. Inline handlers are convenient for simple operations, while method handlers are better for complex logic.
<template>
<div>
<!-- Inline handler -->
<button @click="count++">Count: {{ count }}</button>
<!-- Method handler -->
<button @click="handleClick">Click Me</button>
<!-- Method with arguments -->
<button @click="greet('Hello', $event)">Greet</button>
<!-- Multiple handlers -->
<button @click="logAction('click'), incrementCount()">
Multi Handler
</button>
</div>
</template>
<script>
export default {
data() {
return { count: 0 };
},
methods: {
handleClick() {
this.count++;
console.log("Clicked! Count:", this.count);
},
greet(message, event) {
console.log(message, event.target.tagName);
},
logAction(action) {
console.log("Action:", action);
},
incrementCount() {
this.count++;
},
},
};
</script>
Event Modifiers
Vue provides modifiers that handle common event-related tasks declaratively, keeping your methods focused on business logic rather than DOM mechanics.
<template>
<div>
<!-- .prevent — calls event.preventDefault() -->
<form @submit.prevent="onSubmit">
<input v-model="email" type="email" />
<button type="submit">Submit</button>
</form>
<!-- .stop — calls event.stopPropagation() -->
<div @click="outerClick">
Outer
<button @click.stop="innerClick">Inner (won't bubble)</button>
</div>
<!-- .once — handler fires only once -->
<button @click.once="trackFirstClick">Track First Click</button>
<!-- .self — only fires if event target is the element itself -->
<div @click.self="onDivClick" class="container">
<button>Click me (won't trigger div handler)</button>
</div>
<!-- Chained modifiers -->
<a @click.prevent.stop="handleLink" href="/some-page">Link</a>
</div>
</template>
Key and Mouse Modifiers
Vue provides modifiers for keyboard and mouse events, making it easy to respond to specific keys or mouse buttons.
<template>
<div>
<!-- Key modifiers -->
<input @keyup.enter="submitSearch" placeholder="Press Enter to search" />
<input @keyup.escape="clearField" />
<input @keydown.tab="handleTab" />
<!-- Exact modifier — only fires with exact key combo -->
<input @keyup.ctrl.enter="submitAndClose" />
<div @click.ctrl.exact="ctrlOnlyClick">Ctrl+Click only</div>
<!-- Mouse button modifiers -->
<div @click.right.prevent="showContextMenu">Right-click me</div>
<div @click.middle="openInNewTab">Middle-click me</div>
</div>
</template>
Custom Events with $emit
Child components communicate with parents by emitting custom events using $emit. The parent listens for these events with v-on. This pattern is the primary mechanism for child-to-parent data flow in Vue.
<!-- ChildComponent.vue -->
<template>
<div>
<button @click="$emit('increment')">+1</button>
<button @click="$emit('increment-by', 5)">+5</button>
<button @click="submitForm">Submit</button>
</div>
</template>
<script>
export default {
emits: ["increment", "increment-by", "submit"],
methods: {
submitForm() {
const formData = { name: "Alice", email: "alice@test.com" };
this.$emit("submit", formData);
},
},
};
</script>
<!-- ParentComponent.vue -->
<template>
<div>
<p>Count: {{ count }}</p>
<ChildComponent
@increment="count++"
@increment-by="(n) => count += n"
@submit="handleSubmit"
/>
</div>
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: { ChildComponent },
data() {
return { count: 0 };
},
methods: {
handleSubmit(formData) {
console.log("Form submitted:", formData);
},
},
};
</script>
Tip: Always declare emitted events in the emits option. This serves as documentation, enables validation, and helps Vue distinguish custom events from native DOM events on the component's root element.
Key Takeaways
- Use
@event(shorthand forv-on:event) to listen for DOM and custom events. - Event modifiers (
.prevent,.stop,.once,.self) handle common patterns declaratively. - Key modifiers (
.enter,.escape,.ctrl) simplify keyboard event handling. - Child components emit custom events with
$emitfor upward communication. - Declare emitted events in the
emitsoption for documentation and validation.