本文 AI 產出,尚未審核
Vue3
單元:模板語法(Template Syntax)
主題:v‑on 事件綁定(@click 簡寫)
簡介
在 Vue3 中,事件綁定是讓使用者與介面互動的核心機制。
透過 v-on(或其縮寫 @)可以把 DOM 事件(如 click、input、keyup)與組件的方法連結起來,讓資料流在 View → Model → View 之間自動同步。
如果不了解正確的事件寫法,常會出現 點擊無反應、多次觸發 或 效能瓶頸 等問題。
本篇文章將從最基本的語法說起,逐步帶你掌握實務上常用的技巧與最佳實踐,讓你在開發 Vue3 應用時,能以簡潔且可維護的方式處理所有使用者互動。
核心概念
1. 基本語法:v-on 與 @ 的差別
| 寫法 | 說明 |
|---|---|
v-on:click="handleClick" |
完整寫法,適合教學或需要明確顯示指令名稱的情況 |
@click="handleClick" |
簡寫,Vue 官方推薦的日常寫法,等同於 v-on:click |
<!-- 完整寫法 -->
<button v-on:click="handleClick">完整寫法</button>
<!-- 簡寫 -->
<button @click="handleClick">簡寫</button>
註:
@只是一個語法糖,最終會在編譯階段被轉換成v-on。
2. 直接呼叫方法 vs. 內聯函式
2.1 呼叫組件內的方法
<script setup>
function handleClick() {
console.log('按鈕被點擊!')
}
</script>
<template>
<button @click="handleClick">點我</button>
</template>
2.2 使用內聯函式(匿名函式)
<button @click="() => console.log('內聯函式')">點我</button>
⚠️ 注意:內聯函式會在每次渲染時重新建立,若在大量資料渲染的列表中使用,可能造成不必要的效能開銷。建議在 迴圈或大量元素 中改用 方法引用。
3. 事件修飾子(Modifiers)
Vue 為常見的事件行為提供了 修飾子,讓你不必在 JavaScript 中手動處理。
| 修飾子 | 功能 |
|---|---|
.stop |
阻止事件冒泡 (event.stopPropagation()) |
.prevent |
防止預設行為 (event.preventDefault()) |
.capture |
使用捕獲階段 |
.once |
只觸發一次 |
.passive |
告訴瀏覽器事件不會呼叫 preventDefault()(提升滾動效能) |
.self |
只在事件目標本身觸發時執行 |
<!-- 點擊時阻止冒泡,同時只觸發一次 -->
<button @click.once.stop="handleClick">只點一次且不冒泡</button>
<!-- 表單提交時防止預設送出 -->
<form @submit.prevent="onSubmit">
<button type="submit">送出</button>
</form>
4. 傳遞參數給事件處理函式
4.1 直接傳遞靜態參數
<button @click="handleClick('hello')">傳字串</button>
4.2 傳遞事件物件 ($event)
<input @input="handleInput($event)" placeholder="輸入文字" />
function handleInput(event) {
console.log('輸入內容:', event.target.value)
}
4.3 結合多個參數
<button @click="handleClick(item.id, $event)">傳 ID + 事件</button>
function handleClick(id, event) {
console.log('被點擊的項目 ID:', id)
// 例如:event.stopPropagation()
}
小技巧:若只有一個參數且不需要
$event,可以直接寫@click="handleClick(item.id)";若同時需要$event,必須明確寫出$event,否則會被視為普通參數。
5. 動態事件名稱
有時候事件名稱是根據資料決定的(例如根據 type 動態切換 click、mouseenter),Vue 允許使用 方括號 來綁定動態事件。
<button :[eventName]="handleDynamic">動態事件</button>
<script setup>
import { ref } from 'vue'
const eventName = ref('click') // 可以改成 'mouseenter'、'dblclick' 等
function handleDynamic(event) {
console.log('觸發的事件是:', event.type)
}
</script>
應用情境:在自訂的 UI 元件庫中,根據使用者傳入的
trigger屬性決定是click還是hover觸發。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| 內聯函式過度使用 | 在 v-for 產生大量元素時,每個元素都會產生新的函式,導致 重新渲染 成本升高。 |
把邏輯抽成組件方法或使用 emit 方式傳遞事件。 |
忘記傳 $event |
想要取得原始 DOM 事件卻忘了加 $event,結果拿到的是 undefined。 |
必須明確寫 @click="handle($event)"。 |
| 事件修飾子與自訂事件衝突 | 自訂組件的 emit 事件若同時使用修飾子,修飾子只會作用在原生 DOM 上,不會 影響 emit。 |
若需要阻止冒泡,請在子組件內部自行呼叫 event.stopPropagation()。 |
使用 event.preventDefault() 但忘記 .prevent |
手動在方法裡寫 event.preventDefault(),但在模板忘記傳 event,導致錯誤。 |
使用 .prevent 修飾子,或確保方法參數正確。 |
一次性事件忘記 .once |
需要只執行一次的初始化操作,卻寫成普通 @click,導致多次觸發。 |
加上 .once,或在方法內自行移除監聽。 |
最佳實踐
- 盡量使用簡寫
@,保持模板乾淨。 - 將事件處理邏輯寫在
<script>中,避免在模板內寫過長的表達式。 - 適度使用修飾子,減少在 JavaScript 裡手動調用
stopPropagation、preventDefault。 - 在大量渲染的列表中,使用
key+ 方法引用,避免每筆資料產生新函式。 - 對於自訂組件,使用
emit讓父層自行決定要監聽哪個事件,保持組件的 單向資料流。
實際應用場景
| 場景 | 需求 | 範例程式碼 |
|---|---|---|
| 表單送出 | 防止預設送出、驗證後才提交 | html<br><form @submit.prevent="onSubmit"><button type="submit">送出</button></form> |
| 切換顯示/隱藏 | 點擊按鈕切換 show 狀態 |
html<br><button @click="show = !show">{{ show ? '隱藏' : '顯示' }}</button><div v-if="show">內容</div> |
| 列表項目點擊 | 取得點擊項目的 ID 並傳給父層 | html<br><li v-for="item in items" :key="item.id" @click="select(item.id)">{{ item.name }}</li> |
| 拖曳與拖放 | 使用 .stop 防止父層的 click 觸發 |
html<br><div @click="parentClick"><span @click.stop="childClick">子元素</span></div> |
| 動態觸發方式 | 根據屬性決定是 click 或 hover | html<br><button :[trigger]="handleAction">動態觸發</button> |
總結
v-on是 Vue3 處理事件的根本指令,@為最常使用的簡寫。- 方法引用、內聯函式、事件修飾子、參數傳遞 以及 動態事件名稱,是組合使用的四大要素。
- 避免在大量渲染的元素中濫用內聯函式,善用
key、方法抽離與emit,可提升效能與可維護性。 - 透過修飾子(如
.stop、.prevent、.once)可以把常見的 DOM 操作交給模板處理,讓程式碼更乾淨。
掌握了 @click(以及其他事件)的寫法與最佳實踐,您就能在 Vue3 中快速構建互動豐富、效能優化的前端介面。祝開發順利,持續玩出好作品! 🚀