# [事件](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html)
## 什么是事件
- 事件是視圖層到邏輯層的通訊方式。
- 事件可以將用戶的行為反饋到邏輯層進行處理。
- 事件可以綁定在組件上,當達到觸發事件,就會執行邏輯層中對應的事件處理函數。
- 事件對象可以攜帶額外信息,如 id, dataset, touches。
## 事件的使用方式
- 在組件中綁定一個事件處理函數。
如`bindtap`,當用戶點擊該組件的時候會在該頁面對應的Page中找到相應的事件處理函數。
```html
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
```
- 在相應的Page定義中寫上相應的事件處理函數,參數是event。
```js
Page({
tapName: function(event) {
console.log(event)
}
})
```
- 可以看到log出來的信息大致如下:
```json
{
"type":"tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi":"WeChat"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi":"WeChat"
}
},
"detail": {
"x":53,
"y":14
},
"touches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}],
"changedTouches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}]
}
```
## 事件詳解
### 事件分類
事件分為冒泡事件和非冒泡事件:
1. 冒泡事件:當一個組件上的事件被觸發后,該事件會向父節點傳遞。
2. 非冒泡事件:當一個組件上的事件被觸發后,該事件不會向父節點傳遞。
WXML的冒泡事件列表:
| 類型 | 觸發條件 | 最低版本 |
| ------------------ | ---------------------------------------- | ---------------------------------------- |
| touchstart | 手指觸摸動作開始 | |
| touchmove | 手指觸摸后移動 | |
| touchcancel | 手指觸摸動作被打斷,如來電提醒,彈窗 | |
| touchend | 手指觸摸動作結束 | |
| tap | 手指觸摸后馬上離開 | |
| longpress | 手指觸摸后,超過350ms再離開,如果指定了事件回調函數并觸發了這個事件,tap事件將不被觸發 | [1.5.0](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/compatibility.html) |
| longtap | 手指觸摸后,超過350ms再離開(推薦使用longpress事件代替) | |
| transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結束后觸發 | |
| animationstart | 會在一個 WXSS animation 動畫開始時觸發 | |
| animationiteration | 會在一個 WXSS animation 一次迭代結束時觸發 | |
| animationend | 會在一個 WXSS animation 動畫完成時觸發 | |
**注:除上表之外的其他組件自定義事件如無特殊聲明都是非冒泡事件,如<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件,(詳見各個組件)**
### 事件綁定和冒泡
事件綁定的寫法同組件的屬性,以 key、value 的形式。
- key 以`bind`或`catch`開頭,然后跟上事件的類型,如`bindtap`、`catchtouchstart`。自基礎庫版本 [1.5.0](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/compatibility.html) 起,`bind`和`catch`后可以緊跟一個冒號,其含義不變,如`bind:tap`、、`catch:touchstart`。
- value 是一個字符串,需要在對應的 Page 中定義同名的函數。不然當觸發事件的時候會報錯。
`bind`事件綁定不會阻止冒泡事件向上冒泡,`catch`事件綁定可以阻止冒泡事件向上冒泡。
如在下邊這個例子中,點擊 inner view 會先后調用`handleTap3`和`handleTap2`(因為tap事件會冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父節點傳遞),點擊 middle view 會觸發`handleTap2`,點擊 outer view 會觸發`handleTap1`。
```
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>
```
### 事件的捕獲階段
自基礎庫版本 [1.5.0](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/compatibility.html) 起,觸摸類事件支持捕獲階段。捕獲階段位于冒泡階段之前,且在捕獲階段中,事件到達節點的順序與冒泡階段恰好相反。需要在捕獲階段監聽事件時,可以采用`capture-bind`、`capture-catch`關鍵字,后者將中斷捕獲階段和取消冒泡階段。
在下面的代碼中,點擊 inner view 會先后調用`handleTap2`、`handleTap4`、`handleTap3`、`handleTap1`。
```
<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
```
如果將上面代碼中的第一個`capture-bind`改為`capture-catch`,將只觸發`handleTap2`。
```
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
```
### 事件對象
如無特殊說明,當組件觸發事件時,邏輯層綁定該事件的處理函數會收到一個事件對象。
**BaseEvent 基礎事件對象屬性列表:**
| 屬性 | 類型 | 說明 |
| ---------------------------------------- | ------- | --------------- |
| [type](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#type) | String | 事件類型 |
| [timeStamp](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#timeStamp) | Integer | 事件生成時的時間戳 |
| [target](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#target) | Object | 觸發事件的組件的一些屬性值集合 |
| [currentTarget](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#currenttarget) | Object | 當前組件的一些屬性值集合 |
**CustomEvent 自定義事件對象屬性列表(繼承 BaseEvent):**
| 屬性 | 類型 | 說明 |
| ---------------------------------------- | ------ | ----- |
| [detail](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#detail) | Object | 額外的信息 |
**TouchEvent 觸摸事件對象屬性列表(繼承 BaseEvent):**
| 屬性 | 類型 | 說明 |
| ---------------------------------------- | ----- | ---------------------- |
| [touches](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#touches) | Array | 觸摸事件,當前停留在屏幕中的觸摸點信息的數組 |
| [changedTouches](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#changedTouches) | Array | 觸摸事件,當前變化的觸摸點信息的數組 |
**特殊事件: <canvas/> 中的觸摸事件不可冒泡,所以沒有 currentTarget。**
### type
代表事件的類型。
### timeStamp
頁面打開到觸發事件所經過的毫秒數。
### target
觸發事件的源組件。
| 屬性 | 類型 | 說明 |
| ---------------------------------------- | ------ | --------------------------- |
| id | String | 事件源組件的id |
| tagName | String | 當前組件的類型 |
| [dataset](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#dataset) | Object | 事件源組件上由`data-`開頭的自定義屬性組成的集合 |
### currentTarget
事件綁定的當前組件。
| 屬性 | 類型 | 說明 |
| ---------------------------------------- | ------ | -------------------------- |
| id | String | 當前組件的id |
| tagName | String | 當前組件的類型 |
| [dataset](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/event.html#dataset) | Object | 當前組件上由`data-`開頭的自定義屬性組成的集合 |
**說明: target 和 currentTarget 可以參考上例中,點擊 inner view 時,handleTap3 收到的事件對象 target 和 currentTarget 都是 inner,而 handleTap2 收到的事件對象 target 就是 inner,currentTarget 就是 middle。**
#### dataset
在組件中可以定義數據,這些數據將會通過事件傳遞給 SERVICE。 書寫方式: 以`data-`開頭,多個單詞由連字符`-`鏈接,不能有大寫(大寫會自動轉成小寫)如`data-element-type`,最終在 event.currentTarget.dataset 中會將連字符轉成駝峰`elementType`。
**示例:**
```
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
```
```
Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // - 會轉為駝峰寫法
event.currentTarget.dataset.alphabeta === 2 // 大寫會轉為小寫
}
})
```
### touches
touches 是一個數組,每個元素為一個 Touch 對象(canvas 觸摸事件中攜帶的 touches 是 CanvasTouch 數組)。 表示當前停留在屏幕上的觸摸點。
#### Touch 對象
| 屬性 | 類型 | 說明 |
| ---------------- | ------ | ----------------------------------- |
| identifier | Number | 觸摸點的標識符 |
| pageX, pageY | Number | 距離文檔左上角的距離,文檔的左上角為原點 ,橫向為X軸,縱向為Y軸 |
| clientX, clientY | Number | 距離頁面可顯示區域(屏幕除去導航條)左上角距離,橫向為X軸,縱向為Y軸 |
#### CanvasTouch 對象
| 屬性 | 類型 | 說明 | 特殊說明 |
| ---------- | ------ | ---------------------------------------- | ---- |
| identifier | Number | 觸摸點的標識符 | |
| x, y | Number | 距離 Canvas 左上角的距離,Canvas 的左上角為原點 ,橫向為X軸,縱向為Y軸 | |
### changedTouches
changedTouches 數據格式同 touches。 表示有變化的觸摸點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。
### detail
自定義事件所攜帶的數據,如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息,詳見[組件](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/wxml/wxml-component.md)定義中各個事件的定義。
點擊事件的`detail` 帶有的 x, y 同 pageX, pageY 代表距離文檔左上角的距離。
- 簡介
- 第一章 公眾號開發
- 使用微信JSSDK
- 接口權限配置
- 分享接口
- 隱藏按鈕項
- 微信支付
- 第二章 小程序開發
- 基礎知識
- 分包加載
- WXSS樣式表
- 配置
- app.json配置
- window
- tabBar
- page.json配置
- 邏輯層
- app.js
- 場景值
- page.js
- 初始化數據
- 生命周期函數
- 頁面相關事件處理函數
- 事件處理函數
- 頁面實例方法
- 路由
- 文件作用域
- 模塊化
- 視圖層
- 模板語法
- 列表渲染
- 條件渲染
- 模板
- 事件
- 引用
- WXS語法規范
- WXS數據類型
- WXS控制流程
- WXS基礎類庫
- 組件
- 視圖容器
- view
- scroll-view
- swiper
- movable-view
- cover-view
- 基礎組件
- icon
- text
- rich-text
- progress
- 表單組件
- button
- checkbox
- form
- input
- label
- picker
- picker-view
- radio
- slider
- switch
- textarea
- 導航組件
- navigator
- 媒體組件
- audio
- image
- video
- camera
- 地圖組件
- map
- 畫布組件
- canvas
- 開放能力
- web-view
- 自定義組件
- 組件模版和樣式
- Component
- 組件傳值
- 組件事件
- Behaviors
- 組件間關系
- 網絡請求
- wx.request
- 微信登錄
- 獲取 openid 和 unionid
- 獲取用戶信息
- 將 wx.request 封裝為 promise
- 上傳圖片接口封裝
- 數據存儲
- 存儲數據和讀取數據
- 獲取數據緩存信息
- 移除數據緩存
- 獲取用戶設置
- openSetting
- getSetting
- 第三章 小游戲開發
- 參考資料