今天這篇會先介紹 v-on
的語法和修飾符,熟悉的人可以考慮跳過這個部份。
再來會提到自己在學習 v-on
時的疑惑:
console.log
?」如果你也很好奇,就一起來看看吧! (不好奇的話就跳過吧哈哈)
最後會補充 .passive
修飾符,這個修飾符對應到 addEventListener 的 passive
option,是我自己之前比較陌生的部份!
v-on
快速通關:語法簡介console.log
console.log
app.config.globalProperties
自定義所有模板都可以取到的全域屬性.passive
修飾符v-on
快速通關v-on:
v-on
指令是用來為元素綁定事件監聽器v-on
的部份可以縮寫為 @
。Argument
type
屬性,鍵的名稱可以參考 MDN - Events
emit
來發送自定義事件Modifiers
Vue 針對常用的事件邏輯處理,提供對應的修飾符(modifier),開發者不用一直寫重複的程式碼,也讓 handler 內的程式碼變得更簡潔,並且修飾符可以串接使用。
.stop
:阻止事件冒泡,相當於 event.stopPropagation()
.prevent
:取消事件的預設行為,相當於 event.preventDefault()
.self
:只在綁定監聽器的元素&觸發監聽器的元素相等才執行,即 event.target === event.currentTarget
還有對應到 addEventListener 三個 option 的修飾符:
addEventListener(type, listener, options = {
capture: true,
once: true,
passive: true,
})
.capture
: 切換成捕獲模式(capture).once
:只觸發一次,觸發後就自動移除監聽.passive
:告訴瀏覽器這個 handler 內不會呼叫 event.preventDefault()
,通常用在 touch 相關的事件,可以讓行動裝置上的頁面滑動更流暢;不可以和 .prevent
修飾符同時使用。(發現自己對 .passive
並不熟悉,這部份補充在最後)按鍵修飾符:監聽鍵盤相關事件時,通常需要確認使用的按鍵,在 Vue 可以透過 Key modifier 做到,鍵的名稱可以參考 MDN - Key values for keyboard events。
針對常用的按鍵提供別名:
.enter
.tab
.delete
(包含 "Delete" 和 "Backspace").esc
.space
.up
.down
.left
.right
系統鍵修飾符:和一般按鍵不同,事件觸發時,系統鍵必須處於按下的狀態,通常會跟其他按鍵組合使用。
.ctrl
.alt
.shift
.meta
滑鼠按鍵修飾符:.left
、.right
、.middle
可以配合 mouseEvent 使用。
嚴格修飾符 .exact
:想要嚴格符合設定才會觸發事件,可以使用 .exact
來做修飾,以 click
為例:
@click.exact
: 什麼按紐都不按點擊按鈕才會觸發事件。@click
: 在點擊時按住任何按鈕都會觸發事件。Valuev-on
根據綁定的 value 不同分為兩種:
<button @click="warn">
Submit
</button>
function warn(event) {
// 可以取到原生的 event 物件
if (event) {
event.preventDefault()
}
window.alert("現在還不能送出");
}
<button @click="count++">+1</button>
<button @click="userInput = ''">Reset</button>
function warn(message, event) {
// 可以取到原生的 event 物件
if (event) {
event.preventDefault()
}
alert(message)
}
$event
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
event
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
Submit
</button>
console.log
在 Vue 模板測試 v-on
event handler,如:在父元件監聽子元件 emit 事件時,會很直覺想用 inline handler 搭配 console.log()
去印東西,確認有監聽到事件。
像這樣:
<template>
<button @click="console.log('點擊了按鈕')">按鈕</button>
</template>
或是這樣:
<template>
<BaseInput
:modelValue="userName"
@update:modelValue="console.log('輸入了名字')"
/>
</template>
結果就是收到無數的報錯QQ
像這樣:
這是因為 Vue 預設 template 中的表達式只能使用部份的全域物件,例如:Number
, Array
, Math
, Date
等等,其中不包括 console
跟 window
!
所以每次在 template 讀到 console.log
時, Vue 無法取用到全域的 console
,它會在元件內部找尋 console
這個變數,所以相關報錯通常會是無法讀取 undefined
(reading 'log'
)。
同理,在 Vue 預設的情境下,我們也沒辦法在 template 調用 window.alert()
,或 window 底下相關的變數或函式。
但我們可以透過 app
實例調整設定,做法很簡單。
最後附上 Vue template 可以使用的完整 global
清單如下: 原始碼連結
const GLOBALS_WHITE_LISTED =
'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'
console.log
我們可以透過 app.config.globalProperties
將 console
註冊為所有元件實例都可以取用到的全域物件。
在 main.js
中加入這段程式碼,就可以在所有 Vue template 中使用 console.log
。
app.config.globalProperties.console = console;
記得要在 app
實例建立之後,才可以透過 .config
去設定。
const app = createApp(App);
app.config.globalProperties.console = console;
app.mount("#app");
Vue.property
去設定全域屬性。.passive
修飾符.passive
修飾符會對應到 addEventListener 的 passive
option (預設值為 false
):
addEventListener(type, listener, {
passive: true,
})
將 passive 選項設置為 true
就是在告訴瀏覽器:這個事件 handler 裡面不會呼叫 event.preventDefault()
,你可以直接響應預設行為。
這樣有什麼好處?
可以優化效能,提昇使用者體驗。
因為瀏覽器事先不知道 handler 裡面是否會呼叫 event.preventDefault()
來阻止預設行為,所以瀏覽器需要先執行一次 handler,花時間確定裡面有沒有呼叫 event.preventDefault()
,才決定是否要響應預設行為。
適合拿來優化高頻率觸發的事件監聽器,例如:手機的 touch 事件,瀏覽器就不用在每次使用者開始滑動的時候,花時間重新確認 handler 裡面是否呼叫 event.preventDefault()
,導致滑動上的微卡頓。
passive
option根據 MDN 的說法,除了 Safari 和 IE,其他多數瀏覽器已經將 Window
、Document
和 Document.body
在 wheel、mousewheel、touchstart 和 touchmove 事件監聽中 passive
選項預設為 true
。
那 scroll 事件呢?這個事件感覺也很適合使用 passive
。
The basic scroll event cannot be canceled, so it does not need to be set passive.
scroll 事件的預設行為本身是不能取消的,所以不需要對這類事件監聽器啟用 passive
選項。
想知道 .passive
修飾符的作用可以看以下資料:
EventTarget.addEventListener()