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.
參考資料:
