事件處理
事件處理是指對系統(tǒng)中任意發(fā)生的一個(gè)活動(dòng)調(diào)用有關(guān)程序或例程進(jìn)行處理。主要目的是使系統(tǒng)正常運(yùn)行。
目錄
監(jiān)聽事件
可以用 v-on
指令監(jiān)聽 DOM 事件,并在觸發(fā)時(shí)運(yùn)行一些 JavaScript 代碼。
示例:
<div id="example-1"> <button v-on:click="counter += 1">Add 1</button> <p>The button above has been clicked {{ counter }} times.</p> </div>
var example1 = new Vue({ el: '#example-1', data: { counter: 0 } })
結(jié)果:
事件處理方法
然而許多事件處理邏輯會(huì)更為復(fù)雜,所以直接把 JavaScript 代碼寫在 v-on
指令中是不可行的。因此 v-on
還可以接收一個(gè)需要調(diào)用的方法名稱。
示例:
<div id="example-2"> <!-- `greet` 是在下面定義的方法名 --> <button v-on:click="greet">Greet</button> </div>
var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, // 在 `methods` 對象中定義方法 methods: { greet: function (event) { // `this` 在方法里指向當(dāng)前 Vue 實(shí)例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }) // 也可以用 JavaScript 直接調(diào)用方法 example2.greet() // => 'Hello Vue.js!'
結(jié)果:
內(nèi)聯(lián)處理器中的方法
除了直接綁定到一個(gè)方法,也可以在內(nèi)聯(lián) JavaScript 語句中調(diào)用方法:
<div id="example-3"> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </div>
new Vue({ el: '#example-3', methods: { say: function (message) { alert(message) } } })
結(jié)果:
有時(shí)也需要在內(nèi)聯(lián)語句處理器中訪問原始的 DOM 事件??梢杂锰厥庾兞?$event
把它傳入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)"> Submit </button>
// ... methods: { warn: function (message, event) { // 現(xiàn)在我們可以訪問原生事件對象 if (event) event.preventDefault() alert(message) } }
事件修飾符
在事件處理程序中調(diào)用 event.preventDefault()
或 event.stopPropagation()
是非常常見的需求。盡管我們可以在方法中輕松實(shí)現(xiàn)這點(diǎn),但更好的方式是:方法只有純粹的數(shù)據(jù)邏輯,而不是去處理 DOM 事件細(xì)節(jié)。
為了解決這個(gè)問題,Vue.js 為 v-on
提供了事件修飾符。之前提過,修飾符是由點(diǎn)開頭的指令后綴來表示的。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止單擊事件繼續(xù)傳播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重載頁面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修飾符可以串聯(lián) --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修飾符 --> <form v-on:submit.prevent></form> <!-- 添加事件監(jiān)聽器時(shí)使用事件捕獲模式 --> <!-- 即元素自身觸發(fā)的事件先在此處理,然后才交由內(nèi)部元素進(jìn)行處理 --> <div v-on:click.capture="doThis">...</div> <!-- 只當(dāng)在 event.target 是當(dāng)前元素自身時(shí)觸發(fā)處理函數(shù) --> <!-- 即事件不是從內(nèi)部元素觸發(fā)的 --> <div v-on:click.self="doThat">...</div>
使用修飾符時(shí),順序很重要;相應(yīng)的代碼會(huì)以同樣的順序產(chǎn)生。因此,用
v-on:click.prevent.self
會(huì)阻止所有的點(diǎn)擊,而v-on:click.self.prevent
只會(huì)阻止對元素自身的點(diǎn)擊。
2.1.4 新增
<!-- 點(diǎn)擊事件將只會(huì)觸發(fā)一次 --> <a v-on:click.once="doThis"></a>
不像其它只能對原生的 DOM 事件起作用的修飾符,.once
修飾符還能被用到自定義的組件事件上。如果你還沒有閱讀關(guān)于組件的文檔,現(xiàn)在大可不必?fù)?dān)心。
2.3.0 新增
Vue 還對應(yīng) addEventListener
中的 passive
選項(xiàng)提供了 .passive
修飾符。
<!-- 滾動(dòng)事件的默認(rèn)行為 (即滾動(dòng)行為) 將會(huì)立即觸發(fā) --> <!-- 而不會(huì)等待 `onScroll` 完成 --> <!-- 這其中包含 `event.preventDefault()` 的情況 --> <div v-on:scroll.passive="onScroll">...</div>
這個(gè) .passive
修飾符尤其能夠提升移動(dòng)端的性能。
不要把
.passive
和.prevent
一起使用,因?yàn)?nbsp;.prevent
將會(huì)被忽略,同時(shí)瀏覽器可能會(huì)向你展示一個(gè)警告。請記住,.passive
會(huì)告訴瀏覽器你不想阻止事件的默認(rèn)行為。
按鍵修飾符
在監(jiān)聽鍵盤事件時(shí),我們經(jīng)常需要檢查詳細(xì)的按鍵。Vue 允許為 v-on
在監(jiān)聽鍵盤事件時(shí)添加按鍵修飾符:
<!-- 只有在 `key` 是 `Enter` 時(shí)調(diào)用 `vm.submit()` --> <input v-on:keyup.enter="submit">
你可以直接將 KeyboardEvent.key
暴露的任意有效按鍵名轉(zhuǎn)換為 kebab-case 來作為修飾符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,處理函數(shù)只會(huì)在 $event.key
等于 PageDown
時(shí)被調(diào)用。
按鍵碼
keyCode
的事件用法已經(jīng)被廢棄了并可能不會(huì)被最新的瀏覽器支持。
使用 keyCode
特性也是允許的:
<input v-on:keyup.13="submit">
為了在必要的情況下支持舊瀏覽器,Vue 提供了絕大多數(shù)常用的按鍵碼的別名:
.enter
.tab
.delete
(捕獲“刪除”和“退格”鍵).esc
.space
.up
.down
.left
.right
有一些按鍵 (
.esc
以及所有的方向鍵) 在 IE9 中有不同的key
值, 如果你想支持 IE9,這些內(nèi)置的別名應(yīng)該是首選。
你還可以通過全局 config.keyCodes
對象自定義按鍵修飾符別名:
// 可以使用 `v-on:keyup.f1` Vue.config.keyCodes.f1 = 112
系統(tǒng)修飾鍵
2.1.0 新增
可以用如下修飾符來實(shí)現(xiàn)僅在按下相應(yīng)按鍵時(shí)才觸發(fā)鼠標(biāo)或鍵盤事件的監(jiān)聽器。
.ctrl
.alt
.shift
.meta
注意:在 Mac 系統(tǒng)鍵盤上,meta 對應(yīng) command 鍵 (?)。在 Windows 系統(tǒng)鍵盤 meta 對應(yīng) Windows 徽標(biāo)鍵 (?)。在 Sun 操作系統(tǒng)鍵盤上,meta 對應(yīng)實(shí)心寶石鍵 (◆)。在其他特定鍵盤上,尤其在 MIT 和 Lisp 機(jī)器的鍵盤、以及其后繼產(chǎn)品,比如 Knight 鍵盤、space-cadet 鍵盤,meta 被標(biāo)記為“META”。在 Symbolics 鍵盤上,meta 被標(biāo)記為“META”或者“Meta”。
例如:
<!-- Alt + C --> <input @keyup.alt.67="clear"> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div>
請注意修飾鍵與常規(guī)按鍵不同,在和
keyup
事件一起用時(shí),事件觸發(fā)時(shí)修飾鍵必須處于按下狀態(tài)。換句話說,只有在按住ctrl
的情況下釋放其它按鍵,才能觸發(fā)keyup.ctrl
。而單單釋放ctrl
也不會(huì)觸發(fā)事件。如果你想要這樣的行為,請為ctrl
換用keyCode
:keyup.17
。
.exact
修飾符
2.5.0 新增
.exact
修飾符允許你控制由精確的系統(tǒng)修飾符組合觸發(fā)的事件。
<!-- 即使 Alt 或 Shift 被一同按下時(shí)也會(huì)觸發(fā) --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的時(shí)候才觸發(fā) --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 沒有任何系統(tǒng)修飾符被按下的時(shí)候才觸發(fā) --> <button @click.exact="onClick">A</button>
2.2.0 新增
.left
.right
.middle
這些修飾符會(huì)限制處理函數(shù)僅響應(yīng)特定的鼠標(biāo)按鈕。
為什么在 HTML 中監(jiān)聽事件?
你可能注意到這種事件監(jiān)聽的方式違背了關(guān)注點(diǎn)分離 (separation of concern) 這個(gè)長期以來的優(yōu)良傳統(tǒng)。但不必?fù)?dān)心,因?yàn)樗械?Vue.js 事件處理方法和表達(dá)式都嚴(yán)格綁定在當(dāng)前視圖的 ViewModel 上,它不會(huì)導(dǎo)致任何維護(hù)上的困難。實(shí)際上,使用 v-on
有幾個(gè)好處:
1. 掃一眼 HTML 模板便能輕松定位在 JavaScript 代碼里對應(yīng)的方法。
2. 因?yàn)槟銦o須在 JavaScript 里手動(dòng)綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易于測試。
3. 當(dāng)一個(gè) ViewModel 被銷毀時(shí),所有的事件處理器都會(huì)自動(dòng)被刪除。你無須擔(dān)心如何清理它們。