# 事件處理
## [監聽事件](https://cn.vuejs.org/v2/guide/events.html#%E7%9B%91%E5%90%AC%E4%BA%8B%E4%BB%B6 "監聽事件")
可以用`v-on`指令監聽 DOM 事件,并在觸發時運行一些 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
}
})
~~~
結果:
Add 1
The button above has been clicked 0 times.
## [事件處理方法](https://cn.vuejs.org/v2/guide/events.html#%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95 "事件處理方法")
然而許多事件處理邏輯會更為復雜,所以直接把 JavaScript 代碼寫在`v-on`指令中是不可行的。因此`v-on`還可以接收一個需要調用的方法名稱。
示例:
~~~
<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!'
~~~
結果:
Greet
## [內聯處理器中的方法](https://cn.vuejs.org/v2/guide/events.html#%E5%86%85%E8%81%94%E5%A4%84%E7%90%86%E5%99%A8%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95 "內聯處理器中的方法")
除了直接綁定到一個方法,也可以在內聯 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)
}
}
})
~~~
結果:
Say hiSay what
有時也需要在內聯語句處理器中訪問原始的 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)
}
}
~~~
## [事件修飾符](https://cn.vuejs.org/v2/guide/events.html#%E4%BA%8B%E4%BB%B6%E4%BF%AE%E9%A5%B0%E7%AC%A6 "事件修飾符")
在事件處理程序中調用`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`修飾符還能被用到自定義的[組件事件](https://cn.vuejs.org/v2/guide/components-custom-events.html)上。如果你還沒有閱讀關于組件的文檔,現在大可不必擔心。
> 2.3.0 新增
Vue 還對應[`addEventListener`中的`passive`選項](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters)提供了`.passive`修飾符。
~~~
<!-- 滾動事件的默認行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
~~~
這個`.passive`修飾符尤其能夠提升移動端的性能。
不要把`.passive`和`.prevent`一起使用,因為`.prevent`將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,`.passive`會告訴瀏覽器你*不*想阻止事件的默認行為。
## [按鍵修飾符](https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6 "按鍵修飾符")
在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為`v-on`在監聽鍵盤事件時添加按鍵修飾符:
~~~
<!-- 只有在 `key` 是 `Enter` 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
~~~
你可以直接將[`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)暴露的任意有效按鍵名轉換為 kebab-case 來作為修飾符。
~~~
<input v-on:keyup.page-down="onPageDown">
~~~
在上述示例中,處理函數只會在`$event.key`等于`PageDown`時被調用。
### [按鍵碼](https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E7%A0%81 "按鍵碼")
`keyCode`的事件用法[已經被廢棄了](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode)并可能不會被最新的瀏覽器支持。
使用`keyCode`特性也是允許的:
~~~
<input v-on:keyup.13="submit">
~~~
為了在必要的情況下支持舊瀏覽器,Vue 提供了絕大多數常用的按鍵碼的別名:
* `.enter`
* `.tab`
* `.delete`(捕獲“刪除”和“退格”鍵)
* `.esc`
* `.space`
* `.up`
* `.down`
* `.left`
* `.right`
有一些按鍵 (`.esc`以及所有的方向鍵) 在 IE9 中有不同的`key`值, 如果你想支持 IE9,這些內置的別名應該是首選。
你還可以通過全局`config.keyCodes`對象[自定義按鍵修飾符別名](https://cn.vuejs.org/v2/api/#keyCodes):
~~~
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
~~~
## [系統修飾鍵](https://cn.vuejs.org/v2/guide/events.html#%E7%B3%BB%E7%BB%9F%E4%BF%AE%E9%A5%B0%E9%94%AE "系統修飾鍵")
> 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`換用`keyCode`:`keyup.17`。
### [`.exact`修飾符](https://cn.vuejs.org/v2/guide/events.html#exact-%E4%BF%AE%E9%A5%B0%E7%AC%A6 ".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>
~~~
### [鼠標按鈕修飾符](https://cn.vuejs.org/v2/guide/events.html#%E9%BC%A0%E6%A0%87%E6%8C%89%E9%92%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6 "鼠標按鈕修飾符")
> 2.2.0 新增
* `.left`
* `.right`
* `.middle`
這些修飾符會限制處理函數僅響應特定的鼠標按鈕。
## [為什么在 HTML 中監聽事件?](https://cn.vuejs.org/v2/guide/events.html#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8-HTML-%E4%B8%AD%E7%9B%91%E5%90%AC%E4%BA%8B%E4%BB%B6 "為什么在 HTML 中監聽事件?")
你可能注意到這種事件監聽的方式違背了關注點分離 (separation of concern) 這個長期以來的優良傳統。但不必擔心,因為所有的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的 ViewModel 上,它不會導致任何維護上的困難。實際上,使用`v-on`有幾個好處:
1. 掃一眼 HTML 模板便能輕松定位在 JavaScript 代碼里對應的方法。
2. 因為你無須在 JavaScript 里手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易于測試。
3. 當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。
- 內容介紹
- EcmaScript基礎
- 快速入門
- 常量與變量
- 字符串
- 函數的基本概念
- 條件判斷
- 數組
- 循環
- while循環
- for循環
- 函數基礎
- 對象
- 對象的方法
- 函數
- 變量作用域
- 箭頭函數
- 閉包
- 高階函數
- map/reduce
- filter
- sort
- Promise
- 基本對象
- Arguments 對象
- 剩余參數
- Map和Set
- Json基礎
- RegExp
- Date
- async
- callback
- promise基礎
- promise-api
- promise鏈
- async-await
- 項目實踐
- 標簽系統
- 遠程API請求
- 面向對象編程
- 創建對象
- 原型繼承
- 項目實踐
- Classes
- 構造函數
- extends
- static
- 項目實踐
- 模塊
- import
- export
- 項目實踐
- 第三方擴展庫
- immutable
- Vue快速入門
- 理解MVVM
- Vue中的MVVM模型
- Webpack+Vue快速入門
- 模板語法
- 計算屬性和偵聽器
- Class 與 Style 綁定
- 條件渲染
- 列表渲染
- 事件處理
- 表單輸入綁定
- 組件基礎
- 組件注冊
- Prop
- 自定義事件
- 插槽
- 混入
- 過濾器
- 項目實踐
- 標簽編輯
- 移動客戶端開發
- uni-app基礎
- 快速入門程序
- 單頁程序
- 底部Tab導航
- Vue語法基礎
- 模版語法
- 計算屬性與偵聽器
- Class與Style綁定
- 樣式與布局
- Box模型
- Flex布局
- 內置指令
- 基本指令
- v-model與表單
- 條件渲染指令
- 列表渲染指令v-for
- 事件與自定義屬性
- 生命周期
- 項目實踐
- 學生實驗
- 貝店商品列表
- 加載更多數據
- 詳情頁面
- 自定義組件
- 內置組件
- 表單組件
- 技術專題
- 狀態管理vuex
- Flyio
- Mockjs
- SCSS
- 條件編譯
- 常用功能實現
- 上拉加載更多數據
- 數據加載綜合案例
- Teaset UI組件庫
- Teaset設計
- Teaset使用基礎
- ts-tag
- ts-badge
- ts-button
- ta-banner
- ts-list
- ts-icon
- ts-load-more
- ts-segmented-control
- 代碼模版
- 項目實踐
- 標簽組件
- 失物招領客戶端原型
- 發布頁面
- 檢索頁面
- 詳情頁面
- 服務端開發技術
- 服務端開發環境配置
- Koajs快速入門
- 快速入門
- 常用Koa中間件介紹
- 文件上傳
- RestfulApi
- 一個復雜的RESTful例子
- 使用Mockjs生成模擬數據
- Thinkjs快速入門
- MVC模式
- Thinkjs介紹
- 快速入門
- RESTful服務
- RBAC案例
- 關聯模型
- 應用開發框架
- 服務端開發
- PC端管理界面開發
- 移動端開發
- 項目實踐
- 失物招領項目
- 移動客戶端UI設計
- 服務端設計
- 數據庫設計
- Event(事件)
- 客戶端設計
- 事件列表頁面
- 發布頁面
- 事件詳情頁面
- API設計
- image
- event
- 微信公眾號開發
- ui設計規范