Vue 3.0 事件處理

2021-07-16 11:28 更新

#監(jiān)聽事件

我們可以使用 v-on 指令 (通??s寫為 @ 符號(hào)) 來監(jiān)聽 DOM 事件,并在觸發(fā)事件時(shí)執(zhí)行一些 JavaScript。用法為 v-on:click="methodName" 或使用快捷方式 @click="methodName"

例如:

  1. <div id="basic-event">
  2. <button @click="counter += 1">Add 1</button>
  3. <p>The button above has been clicked {{ counter }} times.</p>
  4. </div>

  1. Vue.createApp({
  2. data() {
  3. return {
  4. counter: 1
  5. }
  6. }
  7. }).mount('#basic-event')

結(jié)果: 點(diǎn)擊此處實(shí)現(xiàn)

#事件處理方法

然而許多事件處理邏輯會(huì)更為復(fù)雜,所以直接把 JavaScript 代碼寫在 v-on 指令中是不可行的。因此 v-on 還可以接收一個(gè)需要調(diào)用的方法名稱。

例如:

  1. <div id="event-with-method">
  2. <!-- `greet` 在下面定義的方法名 -->
  3. <button @click="greet">Greet</button>
  4. </div>

  1. Vue.createApp({
  2. data() {
  3. return {
  4. name: 'Vue.js'
  5. }
  6. },
  7. methods: {
  8. greet(event) {
  9. // `this` 內(nèi)部 `methods` 指向當(dāng)前活動(dòng)實(shí)例
  10. alert('Hello ' + this.name + '!')
  11. // `event` 是原生 DOM event
  12. if (event) {
  13. alert(event.target.tagName)
  14. }
  15. }
  16. }
  17. }).mount('#event-with-method')

結(jié)果: 點(diǎn)擊此處實(shí)現(xiàn)

#內(nèi)聯(lián)處理器中的方法

除了直接綁定到一個(gè)方法,也可以在內(nèi)聯(lián) JavaScript 語(yǔ)句中調(diào)用方法:

  1. <div id="inline-handler">
  2. <button @click="say('hi')">Say hi</button>
  3. <button @click="say('what')">Say what</button>
  4. </div>

  1. Vue.createApp({
  2. methods: {
  3. say(message) {
  4. alert(message)
  5. }
  6. }
  7. }).mount('#inline-handler')

結(jié)果: 點(diǎn)擊此處實(shí)現(xiàn)

有時(shí)也需要在內(nèi)聯(lián)語(yǔ)句處理器中訪問原始的 DOM 事件??梢杂锰厥庾兞?$event 把它傳入方法:

  1. <button @click="warn('Form cannot be submitted yet.', $event)">
  2. Submit
  3. </button>

  1. // ...
  2. methods: {
  3. warn(message, event) {
  4. // now we have access to the native event
  5. if (event) {
  6. event.preventDefault()
  7. }
  8. alert(message)
  9. }
  10. }

#多事件處理器

事件處理程序中可以有多個(gè)方法,這些方法由逗號(hào)運(yùn)算符分隔:

  1. <!-- 這兩個(gè) one() 和 two() 將執(zhí)行按鈕點(diǎn)擊事件 -->
  2. <button @click="one($event), two($event)">
  3. Submit
  4. </button>

  1. // ...
  2. methods: {
  3. one(event) {
  4. // first handler logic...
  5. },
  6. two(event) {
  7. // second handler logic...
  8. }
  9. }

#事件修飾符

在事件處理程序中調(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

  1. <!-- 阻止單擊事件繼續(xù)傳播 -->
  2. <a @click.stop="doThis"></a>
  3. <!-- 提交事件不再重載頁(yè)面 -->
  4. <form @submit.prevent="onSubmit"></form>
  5. <!-- 修飾符可以串聯(lián) -->
  6. <a @click.stop.prevent="doThat"></a>
  7. <!-- 只有修飾符 -->
  8. <form @submit.prevent></form>
  9. <!-- 添加事件監(jiān)聽器時(shí)使用事件捕獲模式 -->
  10. <!-- 即內(nèi)部元素觸發(fā)的事件先在此處理,然后才交由內(nèi)部元素進(jìn)行處理 -->
  11. <div @click.capture="doThis">...</div>
  12. <!-- 只當(dāng)在 event.target 是當(dāng)前元素自身時(shí)觸發(fā)處理函數(shù) -->
  13. <!-- 即事件不是從內(nèi)部元素觸發(fā)的 -->
  14. <div @click.self="doThat">...</div>

TIP

使用修飾符時(shí),順序很重要;相應(yīng)的代碼會(huì)以同樣的順序產(chǎn)生。因此,用 v-on:click.prevent.self 會(huì)阻止所有的點(diǎn)擊,而 v-on:click.self.prevent 只會(huì)阻止對(duì)元素自身的點(diǎn)擊。

  1. <!-- 點(diǎn)擊事件將只會(huì)觸發(fā)一次 -->
  2. <a @click.once="doThis"></a>

不像其它只能對(duì)原生的 DOM 事件起作用的修飾符,.once 修飾符還能被用到自定義的組件事件上。如果你還沒有閱讀關(guān)于組件的文檔,現(xiàn)在大可不必?fù)?dān)心。

Vue 還對(duì)應(yīng) addEventListener 中的 passive 選項(xiàng)提供了 .passive 修飾符。

  1. <!-- 滾動(dòng)事件的默認(rèn)行為 (即滾動(dòng)行為) 將會(huì)立即觸發(fā) -->
  2. <!-- 而不會(huì)等待 `onScroll` 完成 -->
  3. <!-- 這其中包含 `event.preventDefault()` 的情況 -->
  4. <div @scroll.passive="onScroll">...</div>

這個(gè) .passive 修飾符尤其能夠提升移動(dòng)端的性能。

TIP

不要把 .passive.prevent 一起使用,因?yàn)?.prevent 將會(huì)被忽略,同時(shí)瀏覽器可能會(huì)向你展示一個(gè)警告。請(qǐng)記住,.passive 會(huì)告訴瀏覽器你不想阻止事件的默認(rèn)行為。

#按鍵修飾符

在監(jiān)聽鍵盤事件時(shí),我們經(jīng)常需要檢查詳細(xì)的按鍵。Vue 允許為 v-on 或者 @ 在監(jiān)聽鍵盤事件時(shí)添加按鍵修飾符:

  1. <!-- 只有在 `key` 是 `Enter` 時(shí)調(diào)用 `vm.submit()` -->
  2. <input @keyup.enter="submit" />

你可以直接將 KeyboardEvent.key 暴露的任意有效按鍵名轉(zhuǎn)換為 kebab-case 來作為修飾符。

  1. <input @keyup.page-down="onPageDown" />

在上述示例中,處理函數(shù)只會(huì)在 $event.key 等于 'PageDown' 時(shí)被調(diào)用。

#按鍵別名

Vue 為最常用的鍵提供了別名:

  • .enter
  • .tab
  • .delete (捕獲“刪除”和“退格”鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

#系統(tǒng)修飾鍵

可以用如下修飾符來實(shí)現(xiàn)僅在按下相應(yīng)按鍵時(shí)才觸發(fā)鼠標(biāo)或鍵盤事件的監(jiān)聽器。

  • .ctrl
  • .alt
  • .shift
  • .meta

提示

注意:在 Mac 系統(tǒng)鍵盤上,meta 對(duì)應(yīng) command 鍵 (?)。在 Windows 系統(tǒng)鍵盤 meta 對(duì)應(yīng) Windows 徽標(biāo)鍵 (?)。在 Sun 操作系統(tǒng)鍵盤上,meta 對(duì)應(yīng)實(shí)心寶石鍵 (◆)。在其他特定鍵盤上,尤其在 MIT 和 Lisp 機(jī)器的鍵盤、以及其后繼產(chǎn)品,比如 Knight 鍵盤、space-cadet 鍵盤,meta 被標(biāo)記為“META”。在 Symbolics 鍵盤上,meta 被標(biāo)記為“META”或者“Meta”。

例如:

  1. <!-- Alt + Enter -->
  2. <input @keyup.alt.enter="clear" />
  3. <!-- Ctrl + Click -->
  4. <div @click.ctrl="doSomething">Do something</div>

TIP

請(qǐng)注意修飾鍵與常規(guī)按鍵不同,在和 keyup 事件一起用時(shí),事件觸發(fā)時(shí)修飾鍵必須處于按下狀態(tài)。換句話說,只有在按住 ctrl 的情況下釋放其它按鍵,才能觸發(fā) keyup.ctrl。而單單釋放 ctrl 也不會(huì)觸發(fā)事件。

#.exact 修飾符

.exact 修飾符允許你控制由精確的系統(tǒng)修飾符組合觸發(fā)的事件。

  1. <!-- 即使 Alt 或 Shift 被一同按下時(shí)也會(huì)觸發(fā) -->
  2. <button @click.ctrl="onClick">A</button>
  3. <!-- 有且只有 Ctrl 被按下的時(shí)候才觸發(fā) -->
  4. <button @click.ctrl.exact="onCtrlClick">A</button>
  5. <!-- 沒有任何系統(tǒng)修飾符被按下的時(shí)候才觸發(fā) -->
  6. <button @click.exact="onClick">A</button>

#鼠標(biāo)按鈕修飾符

  • .left
  • .right
  • .middle

這些修飾符會(huì)限制處理函數(shù)僅響應(yīng)特定的鼠標(biāo)按鈕。

#為什么在 HTML 中監(jiān)聽事件?

你可能注意到這種事件監(jiān)聽的方式違背了關(guān)注點(diǎn)分離 (separation of concern) 這個(gè)長(zhǎng)期以來的優(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 代碼里對(duì)應(yīng)的方法。
  2. 因?yàn)槟銦o(wú)須在 JavaScript 里手動(dòng)綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易于測(cè)試。
  3. 當(dāng)一個(gè) ViewModel 被銷毀時(shí),所有的事件處理器都會(huì)自動(dòng)被刪除。你無(wú)須擔(dān)心如何清理它們。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)