Vue.js Event Handling
Event handling is how your application reacts to user actions — clicks, key presses, mouse movements, and form submissions. Vue uses the v-on directive to listen for these events and run code in response.
The v-on Directive
The syntax is v-on:eventname="handler". The handler can be a method name, an inline expression, or a function.
<div id="app">
<p>Count: {{ count }}</p>
<button v-on:click="increment">Add One</button>
</div>
<script>
Vue.createApp({
data() {
return { count: 0 };
},
methods: {
increment() {
this.count++;
}
}
}).mount("#app");
</script>
The Shorthand — @ Symbol
v-on: can be shortened to just @. This is the most common form you'll see in real Vue code.
<!-- Full syntax --> <button v-on:click="increment">Add One</button> <!-- Shorthand (same result) --> <button @click="increment">Add One</button>
Common DOM Events
┌─────────────────┬────────────────────────────────────┐ │ Event │ When It Fires │ ├─────────────────┼────────────────────────────────────┤ │ click │ User clicks an element │ │ dblclick │ User double-clicks an element │ │ mouseover │ Mouse pointer enters an element │ │ mouseleave │ Mouse pointer leaves an element │ │ keydown │ A keyboard key is pressed │ │ keyup │ A keyboard key is released │ │ submit │ A form is submitted │ │ change │ An input's value changes │ │ input │ User types in an input field │ │ focus │ An element receives focus │ │ blur │ An element loses focus │ └─────────────────┴────────────────────────────────────┘
Inline Handlers
For simple one-line actions, you can write the JavaScript directly in the template without creating a separate method.
<button @click="count++">Increment</button> <button @click="count = 0">Reset</button> <button @click="message = 'Hello!'">Say Hello</button>
Use inline handlers for very simple logic. Move to methods when the logic requires more than one line.
Method Handlers
For anything beyond a simple expression, define a method and reference it by name.
<div id="app">
<p>{{ statusMessage }}</p>
<button @click="handlePurchase">Buy Now</button>
</div>
<script>
Vue.createApp({
data() {
return {
stock: 5,
statusMessage: "Available"
};
},
methods: {
handlePurchase() {
if (this.stock > 0) {
this.stock--;
this.statusMessage = "Purchased! Stock left: " + this.stock;
} else {
this.statusMessage = "Sorry, out of stock.";
}
}
}
}).mount("#app");
</script>
Diagram: Event Handler Flow
User clicks "Buy Now"
│
▼
@click fires → calls handlePurchase()
│
▼
Method checks: this.stock > 0?
│
Yes │ No
│ └──▶ statusMessage = "Sorry, out of stock."
▼
this.stock--
statusMessage = "Purchased! Stock left: 4"
│
▼
Vue updates the <p> element on screen
The Event Object
Vue automatically passes the native browser event object to your method. You can access it by adding a parameter to your method.
<div id="app">
<input @keyup="logKey">
<p>Last key pressed: {{ lastKey }}</p>
</div>
<script>
Vue.createApp({
data() {
return { lastKey: "" };
},
methods: {
logKey(event) {
this.lastKey = event.key;
}
}
}).mount("#app");
</script>
Accessing the Event with Inline Handlers
When using an inline expression, use the special $event variable to access the event object.
<button @click="handleClick($event)">Click Me</button>
methods: {
handleClick(event) {
console.log("Clicked at X:", event.clientX, "Y:", event.clientY);
}
}
Passing Arguments to Methods
You can pass custom data to your method when an event fires.
<div id="app">
<button @click="greet('Alice')">Greet Alice</button>
<button @click="greet('Bob')">Greet Bob</button>
<p>{{ greeting }}</p>
</div>
<script>
Vue.createApp({
data() {
return { greeting: "" };
},
methods: {
greet(name) {
this.greeting = "Hello, " + name + "!";
}
}
}).mount("#app");
</script>
Event Modifiers
Modifiers change how an event behaves. You add them after the event name with a dot. This avoids writing extra code inside your method.
Common Event Modifiers
@click.prevent → Prevents the default browser action
(e.g., stops a link from navigating)
@click.stop → Stops the event from bubbling up to parent elements
@click.once → Event fires only the first time
@submit.prevent → Prevents form from reloading the page
@click.self → Only fires when clicking the element itself,
not its children
Diagram: .prevent Modifier
Without .prevent: User clicks a link → browser navigates to the href URL With @click.prevent: User clicks the link → Vue handles it, browser does NOT navigate Example: <a href="https://example.com" @click.prevent="handleLink"> Click me </a>
Diagram: .stop Modifier (Event Bubbling)
Without .stop: ┌─────────────────────────────┐ ← parent @click fires too │ <div @click="parentClick"> │ │ ┌────────────────────────┐ │ │ │ <button @click="child">│ │ ← user clicks button │ └────────────────────────┘ │ └─────────────────────────────┘ Both childClick AND parentClick fire. With @click.stop on button: User clicks button → only childClick fires parentClick does NOT fire.
Key Modifiers
Key modifiers filter keyboard events by key name. They work with @keyup and @keydown.
<!-- Only fires when Enter is pressed --> <input @keyup.enter="submitSearch"> <!-- Only fires when Escape is pressed --> <input @keyup.esc="clearInput"> <!-- Only fires for arrow keys --> <input @keydown.arrow-up="moveUp"> <input @keydown.arrow-down="moveDown">
Common Key Modifiers
.enter .tab .delete .esc .space .up .down .left .right
Mouse Button Modifiers
@click.left → left mouse button only @click.right → right mouse button only @click.middle → middle mouse button (scroll wheel click)
Multiple Event Handlers
You can call multiple methods from a single event by separating them with commas.
<button @click="saveData(), showNotification()">Save</button>
Practical Example: Interactive Counter with Limits
<div id="app">
<h3>Ticket Quantity</h3>
<button @click="decrease" :disabled="quantity === 0">−</button>
<span> {{ quantity }} </span>
<button @click="increase" :disabled="quantity === maxLimit">+</button>
<p>Total: ${{ quantity * ticketPrice }}</p>
</div>
<script>
Vue.createApp({
data() {
return {
quantity: 1,
maxLimit: 10,
ticketPrice: 25
};
},
methods: {
increase() {
if (this.quantity < this.maxLimit) this.quantity++;
},
decrease() {
if (this.quantity > 0) this.quantity--;
}
}
}).mount("#app");
</script>
Diagram: Counter State Changes
Initial: quantity = 1, Total = $25 Click +3: quantity = 4, Total = $100 Click −1: quantity = 3, Total = $75 At quantity = 0: [−] button is disabled (cannot go below 0) At quantity = 10: [+] button is disabled (cannot exceed max)
Summary
The v-on directive (shorthand @) attaches event listeners to HTML elements. Point it at a method name for complex logic or write an inline expression for simple actions. The native event object is available automatically in methods, or via $event in inline handlers. Event modifiers like .prevent, .stop, and .once handle common behaviors without extra code in your methods. Key modifiers like .enter and .esc filter keyboard events to specific keys.
