在 Vue 的世界裡,@ 符號如同我們日常生活中的耳朵,隨時靈敏地捕捉著周遭的聲音。今天,就讓我們一起探索 Vue 是如何巧妙地管理 DOM 事件的吧!🎧✨
前言沒有梗,就請語言模型寫。
備註一下:但今天不會帶大家走太多 DOM 事件本身的範例,主要是以 Vue 提供的功能和概念為主~
官方文件:我們可以使用 v-on 指令 (簡寫為 @) 來監聽 DOM 事件,並在事件觸發時執行對應的 JavaScript。
v-on:事件名稱="事件處理器"
// 簡寫
@事件名稱="事件處理器"
""
中的參數為:事件處理器(通常叫做 handler
),有兩種用法:
foo()
、count++
。method
名稱,不直接傳遞參數或表達式。method
才會被呼叫。event
。foo
、foo.bar
、foo['bar']
。官方文件:模板編譯器會通過檢查 v-on 的值是否是合法的 JavaScript 標識符或屬性訪問路徑來斷定是何種形式的事件處理器。
(聽起來真的超級抽象的,我們看看範例~)
<script setup>
import { ref } from "vue";
const count = ref(1);
</script>
<template>
<h3>目前數字:{{ count }}</h3>
<button @click="count++">點擊就馬上+1</button>
</template>
<script setup>
function warn(message) {
alert(message);
}
</script>
<template>
<button @click="warn('早點睡覺!')">我是按鈕請點我</button>
</template>
以上兩個範例:
handler
參數為 count++
,是一個簡易的表達式,當點擊按鈕時,這個「表達式會和事件一起」執行。handler
參數為 warn('早點睡覺!')
,'早點睡覺!'
是自定義的參數,當點擊按鈕時,這個「函式及參數會和事件一起」執行。<script setup>
import { ref } from "vue";
const greetMessage = ref("哈囉哈囉哈囉");
const greet = function (event) {
alert(greetMessage.value);
if (event) {
alert(event.target.innerHTML);
}
};
</script>
<template>
<button @click="greet">我是按鈕請點我</button>
</template>
這邊要注意的是:
事件處理器綁定了一個 method
「greet
」,當按下按鈕後,這個方法會單獨被呼叫、執行,並非內聯的與事件一起執行。
而它會自動傳遞原生的 DOM 物件作為參數,因此可以在 method
裡面直接取用 event
。
if (event) {
alert(event.target.innerHTML);
}
event
代表了當前的事件的 DOM 物件,我們可以 .target.innerHTML
拿到 <button @click="greet">我是按鈕請點我</button>
的 innerHTML
「我是按鈕請點我」,並呈現於 alert
。
看看呈現:
我們來比較一下兩者:
handler | handler 的值 | 執行時機 | 原生 DOM 事件傳遞 | 使用情境 |
---|---|---|---|---|
內聯事件處理器 | 表達式 | 事件觸發時,立即執行 | 需要寫 $event 參數或使用箭頭函式 |
簡單的操作/不需要重複使用的情況 |
方法事件處理器 | method 名稱 |
事件觸發後,呼叫該 method |
自動傳遞事件物件 | 需要重複使用/複雜的邏輯處理 |
剛剛有提到內聯事件處理器的特點:
不會自動傳遞該事件的 DOM 元素作為參數,但可以以手動傳參數/箭頭函式來取得。
也就是以下兩種方式:
$event
參數handler
定義為箭頭函式看範例會比較清楚:
<script setup>
function warn(message, event) {
alert(message);
if (event) {
alert(event.target.innerHTML);
}
}
</script>
<template>
<li>於表達式傳入 $event 參數寫法:</li>
<button @click="warn('早點睡覺!', $event)">我是按鈕請點我</button>
<li>handler 寫箭頭函式:</li>
<button
@click="
(event) => {
warn('早點睡覺!', event);
}">我是按鈕請點我
</button>
</template>
<button @click="warn('早點睡覺!', $event)"> 我是按鈕請點我</button>
:$event
參數寫法的語法,其中在 warn()
傳了 $event
參數。handler
定義為箭頭函式的語法,整個 hanlder
包成一個箭頭函式,並在原本的函式中傳遞 event
參數。<button
@click="
(event) => {
warn('早點睡覺!', event);
}">我是按鈕請點我
</button>
來看看兩者在瀏覽器上的呈現:
剛剛介紹了兩個事件處理器,在範例中我們演示了:在表達式內同時處理了邏輯和 DOM 元素的控制,而這在某些情境可能會變得難維護。
而「事件修飾符」是 Vue 提供的簡便工具,可以讓我們分開操作和修飾那些原本比較複雜的功能。
是指令的後綴,用 .
符號表示。
包含:
- .stop:停止傳遞事件,阻止冒泡行為。
- .prevent:停止元素的預設行為。
- .self:只有事件來自綁定元素本身時才觸發,避免來自子元素的觸發行為。
- .capture:設置事件為捕獲模式。
- .once:確保事件處理器只會觸發一次。
- .passive:不呼叫 preventDefault()。
事件修飾符可以連續使用。
<a @click.stop.prevent="doThat"></a>
handler
可以不指定事件處理器。
<form @submit.prevent></form>
由於修飾符是按照順序執行的,因此排列的邏輯會影響作用範圍。
我們看看例子:
.prevent
先於 .self
:@click.prevent.self
step1:阻止所有觸發元素的預設行為。
step2:只有當事件來自綁定元素本身時才觸發。
.self
先於 .prevent
:@click.self.prevent
step1:只有當事件來自綁定元素本身時才觸發。
step2:阻止所有觸發元素的預設行為。
如果!
我們有個父元素包裹著子元素的情境(目前都尚未加修飾符):
<template>
<div @click="parentClick" class="parent">
父元素
<a href="https://www.example.com" @click="childClick" class="child"
>點擊這裡</a>
</div>
</template>
<script setup>
function parentClick() {
alert("父元素被觸發!");
console.log("父元素被觸發!");
}
function childClick(event) {
alert("子元素被觸發!");
console.log("子元素被觸發!");
}
</script>
<div>
:@click
事件會觸發 parentClick
,跳出 alert
、印出文字。<a>
:@click
事件會觸發 childClick
,跳出 alert
、印出文字。@click
事件。我們來看一下效果:
分析一下:
parentClick
。childClick
,經由事件傳遞(向上冒泡),執行 父元素的 @click
事件,執行自己的預設行為跳轉連結。那麼我們對父元素設置兩個情境:
.prevent
先於.self
:.self
先於.prevent
:
直接來執行:
.prevent
先於 .self
parentClick
。childClick
,經由事件傳遞(向上冒泡),執行 父元素的 @click.prevent.self
事件。.prevent
先阻止了元素的預設行為(這個標記會影響子元素和父元素),然後 .self
檢查事件是否來自於本身元素。
因為事件是由子元素觸發的,所以 @click.prevent
不會影響到父元素的行為,父元素的預設行為不會被阻止,子元素的會。
.self
先於 .prevent
parentClick
。childClick
,經由事件傳遞(向上冒泡),執行 父元素的 @click.self.prevent
事件。.self
先檢查事件是否來自於本身元素,因為事件是由子元素觸發的,所以父元素事件先被標記不執行。.prevent
因為在 .self
後面,所以在 .self
時,就限制的作用範圍,阻止事件也只能阻止父元素自己!因此不會影響到子元素。好繞⋯⋯但這也代表了在使用時要特別注意「事件傳遞」和「修飾符」順序的相互影響!
官方文件:在監聽鍵盤事件時,我們經常需要檢查特定的按鍵。Vue 允許在 v-on 或 @ 監聽按鍵事件時添加按鍵修飾符。
也就是:我們可以利用修飾符直接控制我們想要監聽的特定按鍵,不需要手動在 handler
中檢查按鍵的 keyCode
或 key
屬性。
官方文件:Vue 為一些常用的按鍵提供了別名:
包含:
- .enter
- .tab
- .delete (捕獲“Delete”和“Backspace”兩個按鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
我們來以下列情境試試看修飾符功能:
設置一個 input,在其中按下 Enter 鍵再放開,會跳出 alert。
使用監聽事件+修飾符:@keyup.enter,表示:執行 keyup 事件、並監聽按下 Enter 鍵再放開
<script setup>
function handleKeyup(event) {
if (event.key === "Enter") {
alert("你按下了 Enter 鍵又放開!");
}
}
</script>
<template>
<input
type="text"
@keyup.enter="handleKeyup"
placeholder="請按鍵盤上的 Enter 鍵再放開"
/>
</template>
@keyup.enter="handleKeyup"
:這裡使用了 .enter
修飾符指定:表示在 keyup
事件發生時,只有當按下的鍵是 Enter 鍵時才會觸發 handleKeyup
。handleKeyup
函式中:會自動傳入的 DOM 物件,而我們檢查 event.key
是否等於 "Enter"
,如果是,則跳出 alert
。
官方文件:你可以使用以下系統按鍵修飾符來觸發鼠標或鍵盤事件監聽器,只有當按鍵被按下時才會觸發。
- .ctrl
- .alt
- .shift
- .meta
官方文件:請注意,系統按鍵修飾符和常規按鍵不同。與 keyup 事件一起使用時,該按鍵必須在事件發出時處於按下狀態。換句話說,keyup.ctrl 只會在你仍然按住 ctrl 但鬆開了另一個鍵時被觸發。若你單獨鬆開 ctrl 鍵將不會觸發。
和常規按鍵一起使用時:例如,keyup.enter
會在你 鬆開 Enter 鍵
時觸發。
和系統按鍵一起使用時:例如,keyup.ctrl
需要按住 Ctrl 鍵 + 其他鍵 + 鬆開另一個按鍵時
才會觸發。單獨鬆開 Ctrl 鍵
,是不會觸發這個事件的。
官方文件:.exact 修飾符允許精確控制觸發事件所需要的系統修飾符的組合。
exactly,翻譯:精確地;確切地;完全準確地。
也就是,只有當事件「確實」來自於這個元素本身時,才會觸發事件處理器。
可以避免因為子元素的點擊或事件冒泡而執行不必要的事件處理。
我們看看例子:
@click.ctrl="onClick"
事件的觸發條件:按下 Ctrl 鍵 + 點擊按鈕
,觸發 onClick
。
注意:即使同時按下其他鍵,事件也會觸發。
@click.ctrl.exact="onCtrlClick"
事件的觸發條件:按下 Ctrl 鍵 && 沒有按下其他鍵 + 點擊按鈕
,觸發 onClick
。
注意:如果同時按下 Ctrl + Alt + 點擊按鈕
,事件不會觸發。因為 .exact
限制了只有純粹的 Ctrl + 點擊
才會觸發。
@click.exact="onCtrlClick"
事件的觸發條件:沒有按下任何修飾符 + 點擊按鈕,觸發 onClick
。
注意:.exact
限制了只有純粹的點擊才觸發。
用來控制:特定的滑鼠按鍵觸發時,才會執行對應的事件處理器。
今天這篇是事件工具包的介紹,對事件還不是很熟悉的關係,突然又發現自己的菜味很重 GG,但也代表可意識到還有很多東西可以學習(是吧是吧)。
偶們明天見(不講明天要做什麼嗎)
沒看海綿寶寶,第一次用派星機的我
https://github.com/Jamixcs/2024iThome-jamixcs/tree/main/src/components/day22
被列為參考資料在下著實誠惶誠恐啊(つд⊂)
但使用派星機是一定要推的d(`・∀・)b
派星機參考資料也是你那兒哈哈哈哈哈