本文 AI 產出,尚未審核

Vue3

單元:模板語法(Template Syntax)

主題:v‑on 事件綁定(@click 簡寫)


簡介

在 Vue3 中,事件綁定是讓使用者與介面互動的核心機制。
透過 v-on(或其縮寫 @)可以把 DOM 事件(如 clickinputkeyup)與組件的方法連結起來,讓資料流在 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 動態切換 clickmouseenter),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,或在方法內自行移除監聽。

最佳實踐

  1. 盡量使用簡寫 @,保持模板乾淨。
  2. 將事件處理邏輯寫在 <script>,避免在模板內寫過長的表達式。
  3. 適度使用修飾子,減少在 JavaScript 裡手動調用 stopPropagationpreventDefault
  4. 在大量渲染的列表中,使用 key + 方法引用,避免每筆資料產生新函式。
  5. 對於自訂組件,使用 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 中快速構建互動豐富、效能優化的前端介面。祝開發順利,持續玩出好作品! 🚀