在 JS 中有監聽器 addeventListener
,而 Vue 也有自己一套 DOM 元素監聽器的指令 v-on
, Vue 也配置了幾個修飾符來替代像是 preventDefault()
、 stopPropagation()
等等的。
v-on
指令執行簡單事件
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="count++">數字加1</button>
v-on:click="count++"
就是指當 <button>
元素發生 click
事件,就執行 count++
。
執行複雜事件
方法一:綁定方法
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
data:{
userName:'Celeste'
},
methods:{
greet(){
alert(`Hello ${this.userName}`)
}
}
})
</script>
把複雜的事件處理方法寫在 methods
裡,在讓 v-on
接收這個方法,如 greet
,在接收時,該方法並不需要加上 ()
。
當事件(click
)發生時,執行的方法預設有 event
物件,所以無須將 event
設為參數。
方法二:調用方法
Vue 提供 $event
屬性,可以用來取得 DOM event
物件的值。
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet2('Celeste',$event)">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
methods:{
greet2(name,event){
alert(`Hello ${name}`)
console.log(event)
}
}
})
</script>
<!--v-on:事件=執行事件-->
<button type="button" v-on:click="greet">數字加1</button>
<script>
const vm = new Vue({
el:'#vm',
data:{
userName:'Celeste'
},
methods:{
greet(){
alert(`Hello ${this.userName}`)
}
}
})
</script>
v-on
指令在 JS 中,可以透過一些方法來阻止一些預設行為,像是 event.preventDefault()
、 event.stopPropagation()
或是改變事件傳遞的階段,而 Vue 透過加入修飾符也能達到相同的作用。
Vue 提供的修飾符:
.stop
.stop
跟 JS 裡 event.stopPropagation()
目的相同,阻止後續的事件傳遞。
<div class="changeTarget" v-on:click.stop="changeTarget('div')">
<button type="button" v-on:click.stop="changeTarget('button')">changeTarget</button>
</div>
在沒有 .stop
的情況,如果點擊 <button>
,則上層 <div>
跟 <button>
皆會觸發 changeTarget()
,這是因為事件的傳遞預設為 Bubbling
,所以在觸發 changeTarget('button')
後,會接續觸發 changeTarget('div')
,而修飾符 .stop
就是當第一個事件執行後,後續的冒泡事件又或是捕獲事件就會被阻止。
.prevent
.prevent
跟 JS 裡 event.preventDefault()
目的相同,阻止元素的預設行為,像是 <a>
跟 <button>
的預設行為會導致頁面跳轉或重整。
<a href="https://www.google.com/" target="_blank" v-on:click.prevent="changeTarget('a')" >changeTarget</a>
.capture
在 JS 中, addEventListener
事件傳遞預設是 Bubbling
,如果要變成 Capturing
,就需要將第三個參數改成 true
。
在 Vue 裡,如果想把觸發時機點改成 Capturing
,可以直接使用修飾符 .capture
。
<div class="changeTarget" v-on:click.capture="changeTarget('div')">
<button type="button" v-on:click.stop="changeTarget('button')">changeTarget</button>
</div>
.self
在 Vue 文件說明裡,可以知道當元素事件監聽加入修飾符 .self
後,只有當這個元素是 AT_TARGET 階段(透過 event.eventPhase
查詢,值為2)才能觸發該元素的事件。
<!-- only trigger handler if event.target is the element itself -->
<div class="changeTarget" v-on:click.self="changeTarget('div')">
<span class="changeTarget" v-on:click="changeTarget('innerSpan')">
<button type="button" v-on:click="changeTarget('button')">changeTarget</button>
</span>
</div>
跟 .capture.stop
比較
<!-- only trigger handler if event.target is the element itself -->
<div class="changeTarget" v-on:click.capture.self="changeTarget('div')">
<span class="changeTarget" v-on:click.capture.stop="changeTarget('innerSpan')">
<button type="button" v-on:click="changeTarget('button')">changeTarget</button>
</span>
</div>
.capture.stop
是指元素在捕獲階段執行完事件並阻止後續元素的事件發生,但該元素的 event.eventPhase
值還是 1
,但 .self
是指元素只有在 event.eventPhase
值是 2
的情況才能被執行,所以即使設定 <div class="changeTarget" v-on:click.capture.self="changeTarget('div')"></div>
在捕獲階段執行事件,但因為 <div>
的 event.eventPhase
值是 1
,所以事件不被執行。
.once
使用修飾符 .once
,該事件只能被執行1次。
<div class="changeTarget" v-on:click.once="changeTarget('div')">
<span class="changeTarget" v-on:click.once="changeTarget('innerSpan')">
<button type="button" v-on:click.once="changeTarget('button')">changeTarget</button>
</span>
</div>
.passive
看了 MDN 對於參數 passive
的介紹,主要是針對 touch
某些事件在 scrolling
事件發生時,會有停頓延遲的情況,參數 passive
預設是 false
,當參數 passive
改為 true
時,可以改善scrolling
事件停頓延遲這個問題。
MDN-Improving scrolling performance with passive listeners
Improving Scroll Performance with Passive Event Listeners
v-on
指令透過加入按鍵修飾符,以決定使用哪個按鍵來執行事件。
常見的幾個按鍵修飾符如下:
.enter
.tab
.delete
(“删除”和“退格”鍵).esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
單一按鍵修飾符
<input type="text" v-on:keyup.enter="addTodo" v-model="newTodo">
監聽鍵盤中 enter 按鍵的 keyup
事件,當 enter 按鍵被按下再鬆開後就會去執行所綁定的函式 addTodo
。
多個按鍵修飾符
<input type="text" v-on:keyup.alt.67="clear" v-model="newTodo">
監聽鍵盤中 alt 跟 C 按鍵的 keyup
事件,必須特別注意的是當 .alt
、.ctrl
、shift
等修飾鍵與其他按鍵或事件組合時,事件要觸發的話, .alt
、.ctrl
、shift
等修飾鍵是必須處於按下的狀態的,例如同時按下 alt 跟 C 按鍵,並不會觸發 clear
事件,按下 alt 跟 C 按鍵後僅放開 alt 按鍵,也不會觸發事件,只有在按下 alt 跟 C 按鍵後放開 C 按鍵( alt 按鍵仍須持續按著)才會觸發事件。
同理
<button type="button" v-on:click.ctrl="addTodo">addTodo</button>
如果要觸發事件必須是 ctrl 按鍵持續按著並點擊按鈕才能觸發事件。
v-on
指令加入滑鼠按鈕修飾符的狀況下,只有那個滑鼠按鈕才能觸發事件。
.left
.right
.middle
<button type="button" v-on:click.right="addTodo">addTodo</button>
Demo:[DAY08]跟 Vue.js 認識的30天 - Vue 的事件監聽
參考資料: