DAY08 | 跟 Vue.js 認識的30天 - Vue 的事件監聽(`v-on`)
在 JS 中有監聽器 addeventListener
,而 Vue 也有自己一套 DOM 元素監聽器的指令 v-on
, Vue 也配置了幾個修飾符來替代像是 preventDefault()
、 stopPropagation()
等等的。
v-on
指令
執行簡單事件
1 | <!--v-on:事件=執行事件--> |
v-on:click="count++"
就是指當 <button>
元素發生 click
事件,就執行 count++
。
執行複雜事件
方法一:綁定方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!--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
屬性,可以用來取得 DOMevent
物件的值。1
2
3
4
5
6
7
8
9
10
11
12
13<!--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>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!--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()
目的相同,阻止後續的事件傳遞。1
2
3<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>
的預設行為會導致頁面跳轉或重整。1
<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
。1
2
3<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)才能觸發該元素的事件。1
2
3
4
5
6<!-- 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
比較1
2
3
4
5
6<!-- 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次。1
2
3
4
5<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
單一按鍵修飾符
1 | <input type="text" v-on:keyup.enter="addTodo" v-model="newTodo"> |
監聽鍵盤中 enter 按鍵的 keyup
事件,當 enter 按鍵被按下再鬆開後就會去執行所綁定的函式 addTodo
。
多個按鍵修飾符
1 | <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 按鍵仍須持續按著)才會觸發事件。
同理
1 | <button type="button" v-on:click.ctrl="addTodo">addTodo</button> |
如果要觸發事件必須是 ctrl 按鍵持續按著並點擊按鈕才能觸發事件。
加入滑鼠修飾符的 v-on
指令
加入滑鼠按鈕修飾符的狀況下,只有那個滑鼠按鈕才能觸發事件。
.left
.right
.middle
1 | <button type="button" v-on:click.right="addTodo">addTodo</button> |
最後的小確幸: v-on
指令可以用 @
取代。
1 | <input type="text" @keyup.enter="addTodo" v-model="newTodo"> |
Demo:
See the Pen [DAY08]跟 Vue.js 認識的30天 - Vue 的事件監聽 by Celeste6666 (@celeste6666) on CodePen.
參考資料: