---
title: 基础交互事件
summary: "介绍小程序基础交互事件系统，涵盖事件分类、绑定方式、冒泡机制及事件对象的属性结构。"
questions:
  - 涂鸦小程序中冒泡事件和非冒泡事件有什么区别？
  - bind 和 catch 两种事件绑定方式的区别是什么？
  - 事件对象中 target 和 currentTarget 的区别是什么？
  - 如何通过 data- 自定义属性在事件处理中传递数据？
  - TouchEvent 事件对象中 touches 和 changedTouches 分别表示什么？
  - longpress 事件与 tap 事件之间的关系是怎样的？
  - BaseEvent 基础事件对象包含哪些属性？
  - dataset 中连字符命名和驼峰命名的转换规则是什么？
  - Touch 对象中 pageX/pageY 和 clientX/clientY 的区别是什么？
---

## 什么是交互事件

- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上。当达到触发事件，就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息，如 `id`、`dataset` 和 `touches`。

## 事件分类

事件分为冒泡事件和非冒泡事件。

- 冒泡事件：当一个组件上的事件被触发后，该事件会向父节点传递。
- 非冒泡事件：当一个组件上的事件被触发后，该事件不会向父节点传递。

## 事件列表

| 类型               | 触发条件                                                                                    |        |
| ------------------ | ------------------------------------------------------------------------------------------- | ------ |
| touchstart         | 手指触摸动作开始。                                                                          |        |
| touchmove          | 手指触摸后移动。                                                                            |        |
| touchcancel        | 手指触摸动作被打断，如来电提醒，弹窗。                                                      |        |
| touchend           | 手指触摸动作结束。                                                                          |        |
| tap                | 手指触摸后马上离开。                                                                        |        |
| transitionend      | 会在 TYSS transition 或 `createAnimation` 动画结束后触发。                                  |        |
| animationstart     | 会在一个 TYSS animation 动画开始时触发。                                                    |        |
| animationiteration | 会在一个 TYSS animation 一次迭代结束时触发。                                                |        |
| animationend       | 会在一个 TYSS animation 动画完成时触发。                                                    |        |
| longpress          | 手指触摸后，超过 350ms 再离开，如果指定了事件回调函数并触发了这个事件，tap 事件将不被触发。 | 2.13.0 |
| longtap            | 手指触摸后，超过 350ms 再离开（推荐使用 `longpress` 事件代替）。                            | 2.13.0 |

> **说明**：如无特殊声明，除上表之外的其他组件自定义事件都是非冒泡事件，如 `<form />` 的 `submit` 事件，`<input />` 的`input` 事件，`scroll-view` 的 `scroll` 事件。详见各个组件。

## 事件的绑定

模板语法中通过以下两种语法形式，添加事件绑定：

- `bind:{事件名}` 绑定事件。
- `catch:{事件名}` 绑定并阻止事件冒泡。

### 绑定事件

使用 `bind:` 形式绑定事件。

```html
<view bind:tap="handleTap"> Click here! </view>
```

### 绑定并阻止事件冒泡

使用 `catch:` 形式绑定事件。

例如，在下边这个例子中：

1. 单击 inner view 会先后调用 `handleTap3` 和 `handleTap2`。因为 `tap` 事件会冒泡到 middle view，而 middle view 阻止了 `tap` 事件冒泡，不再向父节点传递。
2. 单击 middle view 会触发 `handleTap2`。
3. 单击 outer view 会触发 `handleTap1`。

```html
<view id="outer" bind:tap="handleTap1">
  outer view
  <view id="middle" catch:tap="handleTap2">
    middle view
    <view id="inner" bind:tap="handleTap3"> inner view </view>
  </view>
</view>
```

## 事件对象

如无特殊说明，当组件触发事件时，逻辑层绑定该事件的处理函数会收到一个事件对象。

#### BaseEvent 基础事件对象属性列表

| 属性          | 类型    | 说明                             |
| ------------- | ------- | -------------------------------- |
| type          | String  | 事件类型。                       |
| timeStamp     | Integer | 事件生成时的时间戳。             |
| target        | Object  | 触发事件的组件的一些属性值集合。 |
| currentTarget | Object  | 当前组件的一些属性值集合。       |

#### CustomEvent 自定义事件对象属性列表（继承 BaseEvent）

| 属性   | 类型   | 说明         |
| ------ | ------ | ------------ |
| detail | Object | 额外的信息。 |

#### TouchEvent 触摸事件对象属性列表（继承 BaseEvent）

| 属性           | 类型  | 说明                                           |
| -------------- | ----- | ---------------------------------------------- |
| touches        | Array | 触摸事件，当前停留在屏幕中的触摸点信息的数组。 |
| changedTouches | Array | 触摸事件，当前变化的触摸点信息的数组。         |

### type

代表事件的类型。

### timeStamp

页面打开到触发事件所经过的毫秒数。

### target

触发事件的源组件。

| 属性    | 类型   | 说明                                               |
| ------- | ------ | -------------------------------------------------- |
| id      | String | 事件源组件的 ID。                                  |
| dataset | Object | 事件源组件上由 `data-`开头的自定义属性组成的集合。 |

### currentTarget

事件绑定的当前组件。

| 属性    | 类型   | 说明                                              |
| ------- | ------ | ------------------------------------------------- |
| id      | String | 当前组件的 ID。                                   |
| dataset | Object | 当前组件上由 `data-` 开头的自定义属性组成的集合。 |

> **说明**：`target` 和 `currentTarget` 可以参考上例中，单击 `inner view` 时，`handleTap3` 收到的事件对象 `target` 和 `currentTarget` 都是 `inner`，而 `handleTap2` 收到的事件对象 `target` 就是 `inner`，`currentTarget` 就是 `middle`。

### dataset

在组件节点中可以附加一些自定义数据。这样，在事件中可以获取这些自定义的节点数据，用于事件的逻辑处理。

在模板中，这些自定义数据以 `data-` 开头，多个单词由连字符 `-` 连接。这种写法中，连字符写法会转换成驼峰写法，而大写字符会自动转成小写字符。如：

`data-element-type`，最终会呈现为 event.currentTarget.dataset.`elementType` ；
`data-elementType`，最终会呈现为 event.currentTarget.dataset.`elementtype` 。

示例：

```html
<view data-alpha-beta="1" data-alphaBeta="2" bind:tap="bindViewTap">
  DataSet Test
</view>
```

```js
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 轴。 |

### changedTouches

`changedTouches` 数据格式同 `touches`。表示有变化的触摸点，如从无变有（`touchstart`），位置变化（`touchmove`）以及从有变无（`touchend`、`touchcancel`）。

### detail

自定义事件所携带的数据，如表单组件的提交事件会携带用户的输入，媒体的错误事件会携带错误信息。详见组件定义中各个事件的定义。

单击事件的 `detail` 带有的 `x` 和 `y`，同 `pageX` 和 `pageY`。代表距离文档左上角的距离。

## 示例

### 在组件中绑定一个事件处理函数

如 `bind:tap`，当用户单击该组件的时候，会在该页面对应的 `Page` 中找到相应的事件处理函数。

```html
<view id="abc" data-hi="smart" bind:tap="handleTap"> Click me! </view>
```

在相应的 `Page` 定义中，写上相应的事件处理函数，参数是 `event`。

```js
Page({
  handleTap: function (event) {
    console.log(event);
  },
});
```

可以看到 `log` 出来的 `event` 对象大致如下：

```json
{
  "type": "tap",
  "timeStamp": 3817,
  "target": {
    "id": "abc",
    "offsetLeft": 105,
    "offsetTop": 197,
    "dataset": { "hi": "smart" }
  },
  "currentTarget": {
    "id": "abc",
    "offsetLeft": 105,
    "offsetTop": 197,
    "dataset": { "hi": "smart" }
  },
  "touches": [
    {
      "identifier": 0,
      "pageX": 243,
      "pageY": 209,
      "clientX": 243,
      "clientY": 209
    }
  ],
  "changedTouches": [
    {
      "identifier": 0,
      "pageX": 243,
      "pageY": 209,
      "clientX": 243,
      "clientY": 209
    }
  ]
}
```
