2024-09-17|閱讀時間 ‧ 約 22 分鐘

EP9 - 事件處理

Event Handling 處理使用者觸發了哪些動作,
好奇這能什麼新功能?不就是綁定事件處理而已嗎?
繼續看下去~~

聆聽事件​ - Listening to Events

我們可以使用v-on 指令來監聽 DOM 事件並在事件觸發時運行一些 JavaScript 程式碼,通常我們會將其縮寫為 @ 符號。用法可以是 v-on:click="handler" 或者使用簡寫 @click="handler"

handler 值可以是以下之一:

內聯處理程序(inline handler):當事件觸發時要執行的inline JavaScript(類似於原生的 onclick 屬性)。

方法處理程序(method handler):指向在組件上定義的方法的屬性名稱或路徑

內聯處理程序 - Inline Handlers​

內聯處理程序通常用於簡單的情況,例如:

const count = ref(0)
<button @click="count++">Add 1</button>
<p>Count is: {{ count }}</p>

Try it in the playground

方法處理程序 - Method Handler

許多事件處理程序的邏輯會更複雜,因此不適合使用內聯處理程序。這就是為什麼 v-on 也可以接受要調用的組件方法的名稱或路徑。

const name = ref('Vue.js')

function greet(event) {
alert(`Hello ${name.value}!`)
// `event` 是原生的 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
<!-- `greet` 是上面定義的方法的名稱 -->
<button @click="greet">Greet</button>

Try it in the playground

方法處理程序會自動接收觸發它的原生 DOM 事件對象——在上面的例子中,我們能夠通過 event.target 訪問分派事件的元素。

參見:Typing Event Handlers

方法處理與內聯處理的偵測 - Method vs. Inline Detection

範本編譯器會透過檢查 v-on 的值字串是否為有效的 JavaScript 識別符號或屬性存取路徑來檢測方法處理程序。 例如,foofoo.barfoo['bar'] 會被視為方法處理程序,而 foo()count++ 則會被視為內聯處理程序。

在內聯處理器中調用方法 - Calling Methods in Inline Handlers​

除了直接綁定到方法名稱之外,我們還可以在內聯處理器中調用方法。這使我們能夠傳遞自定義參數到方法中,而不是傳遞原生事件:

function say(message) {
alert(message)
}
<button @click="say('hello')">Say hello</button>
<button @click="say('bye')">Say bye</button>

Try it in the playground

在內聯處理程序中訪問事件參數 - Accessing Event Argument in Inline Handlers​

有時候我們需要在內聯處理程序中訪問原始的 DOM 事件。我們可以使用特殊變量 $event 或內聯箭頭函數來傳遞事件:

<!-- 使用 $event 特殊變量 -->
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>

<!-- 使用內聯箭頭函數 -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
Submit
</button>
function warn(message, event) {
// 現在我們可以訪問原生事件
if (event) {
// 阻止事件的預設行為
event.preventDefault()
}
alert(message)
}

Q:什麼是預設行為?

在網頁開發中,預設行為(Default Behavior)是指瀏覽器在特定事件發生時,會自動執行的一些內建操作。例如:

  1. 表單提交
    • 當你在表單中點擊提交按鈕時,瀏覽器會自動提交表單數據,並重新加載頁面或導航到指定的目標URL。
  2. 超連結點擊
    • 當你點擊超連結(<a> 標籤)時,瀏覽器會自動導航到連結指定的URL。
  3. 文本框輸入
    • 當你在文本框中按下 Enter 鍵時,瀏覽器會自動提交包含該文本框的表單。
  4. 按鈕點擊
    • 當你點擊按鈕時,瀏覽器可能會提交包含該按鈕的表單(如果該按鈕是提交按鈕)。

在 JavaScript 中,你可以使用 event.preventDefault() 來阻止這些預設行為。這樣可以讓你完全控制事件發生後的行為。例如:

  • 阻止表單提交:你可以在表單提交按鈕的點擊事件中使用 event.preventDefault(),然後執行一些自定義的驗證邏輯,如果驗證通過再手動提交表單。
  • 自定義超連結行為:你可以在超連結的點擊事件中使用 event.preventDefault(),然後執行一些自定義的導航邏輯或動畫效果。

以下是一些示例:

阻止表單提交

<form id="myForm">
<input type="text" name="username" />
<button type="submit">提交</button>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault(); // 阻止表單提交的預設行為
alert('表單尚未提交。');
// 你可以在這裡添加自定義的表單處理邏輯
});
</script>

阻止超連結導航

<a href="https://example.com" id="myLink">點擊我</a>

<script>
document.getElementById('myLink').addEventListener('click', function(event) {
event.preventDefault(); // 阻止超連結導航的預設行為
alert('超連結尚未導航。');
// 你可以在這裡添加自定義的導航邏輯
});
</script>

通過這些方法,可以在事件發生時完全控制應用的行為,而不是依賴瀏覽器預設行為。

事件修飾符 - Event Modifiers

在事件處理程序中,通常需要調用 event.preventDefault()event.stopPropagation()。雖然我們可以在方法內輕鬆地執行這些操作,但如果方法僅處理數據邏輯,而不是處理 DOM 事件細節,那會更好。

為了解決這個問題,Vue 提供了事件修飾符,用於 v-on 指令。修飾符是指令的後綴,用點表示。

  • .stop:停止事件的傳播。
  • .prevent:取消事件的預設行為。
  • .self:僅在事件目標為當前元素時觸發處理程序,即事件不是來自子元素。
  • .capture:以捕獲模式添加事件監聽器,即內部元素的事件會先被處理。
  • .once:事件處理程序只觸發一次。
  • .passive:不阻止事件的預設行為,常用於移動設備的觸控事件以提高性能。
<!-- 停止 click 事件的傳播 -->
<a @click.stop="doThis"></a>

<!-- 取消 submit 事件的預設行為,避免重新加載頁面 -->
<form @submit.prevent="onSubmit"></form>

<!-- 修飾符可以鏈接使用 -->
<a @click.stop.prevent="doThat"></a>

<!-- 僅使用修飾符 -->
<form @submit.prevent></form>

<!-- 只在事件目標是該元素時才觸發處理程序 -->
<div @click.self="doThat">...</div>

提示:

  • 使用修飾符的順序很重要,因為相關代碼會按相同順序生成。例如,@click.prevent.self 會阻止元素及其子元素的 click 預設行為,而 @click.self.prevent 只會阻止元素本身的 click 預設行為。

.capture.once.passive 修飾符對應於原生 addEventListener 方法的選項:

<!-- 使用捕獲模式來添加事件監聽器 -->
<!-- 例如:即事件觸發的內部元素會先在這裡處理 -->
<!-- 然後再由該元素處理 -->
<div @click.capture="doThis">...</div>

<!-- 點擊事件最多只會觸發一次 -->
<a @click.once="doThis"></a>

<!-- 滾動事件的預設行為(滾動)會立即發生 -->
<!-- 而不是等 `onScroll` 完成後再發生 -->
<!-- 如果 `onScroll` 包含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>

.passive 修飾符通常與觸控事件監聽器一起使用,以提高移動設備上的性能

提示:

不要將 .passive.prevent 一起使用,因為 .passive 已經告訴瀏覽器你不打算阻止事件的預設行為,如果這樣做,瀏覽器可能會顯示警告。

鍵盤修飾符 - Key Modifiers

當監聽鍵盤事件時,我們經常需要檢查特定的鍵。Vue 允許在監聽鍵盤事件時為 v-on@ 添加鍵盤修飾符:

<!-- 只有當 `key``Enter` 時才會調用 `submit` -->
<input @keyup.enter="submit" />

你可以直接使用任何有效的鍵名,這些鍵名是由 KeyboardEvent.key 提供的,將它們轉換為 kebab-case(連字符小寫命名)作為修飾符。

<input @keyup.page-down="onPageDown" />

在上面的例子中,當 $event.key 等於 'PageDown' 時,處理程序才會被調用。

鍵名別名 - Key Aliases​Vue 為最常用的鍵提供了別名:

  • .enter
  • .tab
  • .delete(涵蓋 "Delete" 和 "Backspace" 鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系統修飾鍵 - System Modifier Keys​

使用以下修飾符來觸發只有在按下相應的修飾鍵時才會觸發的滑鼠或鍵盤事件監聽器:

  • .ctrl
  • .alt
  • .shift
  • .meta

提示:

在 Macintosh 鍵盤上,meta 是命令鍵 (⌘)。在 Windows 鍵盤上,meta 是 Windows 鍵 (⊞)。在 Sun Microsystems 鍵盤上,meta 標記為實心菱形 (◆)。在某些鍵盤上,特別是 MIT 和 Lisp 機器鍵盤及其後繼產品,如 Knight 鍵盤、space-cadet 鍵盤,meta 標記為“META”。在 Symbolics 鍵盤上,meta 標記為“META”或“Meta”。

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

提示:

請注意,修飾鍵不同於普通鍵,當與 keyup 事件一起使用時,必須在事件發出時按下修飾鍵。換句話說,keyup.ctrl 只有在您按住 ctrl 鍵的同時放開另一個鍵時才會觸發。如果您單獨放開 ctrl 鍵,則不會觸發。

.exact 修飾符 - .exact Modifier​

.exact 修飾符用來控制觸發事件所需的系統修飾鍵(如 Ctrl、Alt、Shift、Meta)必須完全符合特定的組合。這意味著你可以指定只有在完全按下某些修飾鍵,且不按其他修飾鍵的情況下,事件才會觸發。

1. 只要 Ctrl 鍵按下即可觸發事件(不考慮其他修飾鍵)

<button @click.ctrl="onClick">A</button>

在這個例子中,只要 Ctrl 鍵被按下,不管是否同時按下其他修飾鍵(如 Alt 或 Shift),onClick 函數都會被觸發。

2. 只有在 Ctrl 鍵按下且沒有其他修飾鍵時才會觸發事件

<button @click.ctrl.exact="onCtrlClick">A</button>

在這個例子中,onCtrlClick 函數只會在 Ctrl 鍵按下的同時,其他修飾鍵(如 Alt、Shift)沒有被按下的情況下觸發。如果同時按下其他修飾鍵,事件將不會被觸發。

3. 當沒有按下任何系統修飾鍵時觸發事件

<button @click.exact="onClick">A</button>

這個例子中,onClick 函數只有在沒有按下任何系統修飾鍵的情況下才會被觸發。如果同時按下了 Ctrl、Alt、Shift 或 Meta 鍵,事件將不會觸發。

鼠標按鈕修飾符​ - Mouse Button Modifiers

  • .left
  • .right
  • .middle

這些修飾符限制事件處理器僅響應由特定鼠標按鈕觸發的事件。

這一篇就覺得蠻好用!假如是傳統的寫法要設定一堆事件很麻煩~
現在有很方便的修飾符可以簡化很多內容~
還是要好好測試一下~省下多少麻煩www





分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.