事件處理


目錄


#為什麼在HTML 中監聽事件?


監聽事件

可以用

v- on

指令監聽DOM 事件,並在觸發時執行一些JavaScript 程式碼。 2.gif

範例:

<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
  }
})

結果:


事件處理方法

然而許多事件處理邏輯會比較複雜,所以直接把JavaScript 程式碼寫在

v-on

指令中是不可行的。因此

v-on

也可以接收一個需要呼叫的方法名稱。

1.gif

範例:

<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` 在方法里指向当前 Vue 实例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})
// 也可以用 JavaScript 直接调用方法
example2.greet() // => 'Hello Vue.js!'

結果:


內嵌處理器中的方法

3.gif

除了直接綁定到一個方法,也可以在內嵌JavaScript 語句中呼叫方法:

<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)
    }
  }
})

結果:


有時也需要在內聯語句處理器中存取原始的DOM 事件。可以用特殊變數

$event 把它傳入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>
// ...
methods: {
  warn: function (message, event) {
    // 现在我们可以访问原生事件对象
    if (event) event.preventDefault()
    alert(message)
  }
}


事件修飾符

##在事件處理程序中呼叫###event.preventDefault()### 或###event.stopPropagation()### 是非常常見的需求。儘管我們可以在方法中輕鬆實現這一點,但更好的方式是:方法只有純粹的資料邏輯,而不是去處理 DOM 事件細節。 ###

為了解決這個問題,Vue.js 為 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令後綴來表示的。

  • .stop

  • .prevent

  • .capture

  • .self

  • ##.once

  • .passive

  • #
    <!-- 阻止单击事件继续传播 -->
    <a v-on:click.stop="doThis"></a>
    
    <!-- 提交事件不再重载页面 -->
    <form v-on:submit.prevent="onSubmit"></form>
    
    <!-- 修饰符可以串联 -->
    <a v-on:click.stop.prevent="doThat"></a>
    
    <!-- 只有修饰符 -->
    <form v-on:submit.prevent></form>
    
    <!-- 添加事件监听器时使用事件捕获模式 -->
    <!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
    <div v-on:click.capture="doThis">...</div>
    
    <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
    <!-- 即事件不是从内部元素触发的 -->
    <div v-on:click.self="doThat">...</div>
使用修飾符時,順序很重要;對應的程式碼會以同樣的順序產生。因此,用 

v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent# 只會阻止對元素自身的點選。

2.1.4 新增

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
#不像它只能對原生的DOM 事件起作用的修飾符,

.once 修飾子也能被用到自訂的元件事件上。如果你還沒有閱讀關於組件的文檔,現在大可不必擔心。

2.3.0 新增

Vue 也對應

addEventListener 中的passive 選項提供了.passive 修飾符。

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

這個

.passive 修飾符尤其能夠提升行動端的效能。

不要把 

.passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。


按鍵修飾符號


在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。 Vue 允許為

v-on 在監聽鍵盤事件時添加按鍵修飾符:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

你可以直接將

KeyboardEvent.key## 暴露的任意有效按鍵名轉換為kebab-case 來作為修飾符。

<input v-on:keyup.page-down="onPageDown">
在上述範例中,處理函數只會在

$event.key

等於 PageDown 時被呼叫。


按鍵碼

#keyCode

 的事件用法已經被廢棄了並且可能不會被最新的瀏覽器支援。

使用
keyCode

特性也是允許的:

<input v-on:keyup.13="submit">
為了在必要的情況下支援舊瀏覽器,Vue 提供了絕大多數常用的按鍵碼的別名:

  • .enter

  • .tab

  • .delete (捕獲「刪除」與「退格」鍵)

  • #.esc

  • .space

  • .up

  • .down

  • #.left

  • #.right

有一些按鍵 (.esc 以及所有的方向鍵) 在 IE9 中有不同的 key 值, 如果你想支援 IE9,這些內建的別名應該是首選。

你也可以透過全域config.keyCodes 物件自訂按鍵修飾符別名

// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112


系統修飾鍵


2.1.0 新增

可以用以下修飾符來實作僅在按下對應按鍵時才觸發滑鼠或鍵盤事件的監聽器。

  • .ctrl

  • #.alt

  • .shift

  • .meta

注意:在 Mac 系統鍵盤上,meta 對應 command 鍵 (?)。在 Windows 系統鍵盤 meta 對應 Windows 標誌鍵 (?)。在 Sun 作業系統鍵盤上,meta 對應實心寶石鍵 (◆)。在其他特定鍵盤上,特別是 MIT 和 Lisp 機器的鍵盤、以及其後繼產品,例如 Knight 鍵盤、space-cadet 鍵盤,而meta 則標示為「META」。在 Symbolics 鍵盤上,meta 標示為「META」或「Meta」。

例如:

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

請注意修飾鍵與常規按鍵不同,在和 keyup 事件一起用時,事件觸發時修飾鍵必須處於按下狀態。換句話說,只有在按住 ctrl 的情況下釋放其它按鍵,才能觸發 keyup.ctrl。而單單釋放 ctrl 也不會觸發事件。如果你想要這樣的行為,請為 ctrl 換用 keyCodekeyup.17


.exact 修飾符

2.5.0 新增

.exact 修飾符可讓你控制由精確的系統修飾符組合觸發的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>


滑鼠按鈕修飾符

#2.2.0 新增

  • .left

    #
  • .right

  • .middle

這些修飾符會限制處理函數僅響應特定的滑鼠按鈕。


為什麼在HTML 中監聽事件?


##你可能注意到這種事件監聽的方式違背了關注點分離(separation of concern) 這個長期以來的優良傳統。但不必擔心,因為所有的 Vue.js 事件處理方法和表達式都嚴格綁定在目前視圖的 ViewModel 上,它不會導致任何維護上的困難。實際上,使用

v-on 有幾個好處:

 1. 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 程式碼裡對應的方法。

 2. 因為你無須在 JavaScript 裡手動綁定事件,你的 ViewModel 程式碼可以是非常純粹的邏輯,和 DOM 完全解耦,更容易測試。

 3. 當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。