# 浅析微信小程序的事件机制

- 作者：知晓程序
- 发布时间：2017-01-18 18:30
- 原文：https://www.ifanr.com/minapp/777925

![event-featured](https://s3.ifanr.com/wp-content/uploads/2017/01/event-Featured.jpg)

**知晓程序是爱范儿旗下专注小程序生态的品牌**，我们已经做了这些：

- **知晓程序公众号（微信号 zxcx0101）：**做最好的小程序媒体，让你了解小程序的一切
- **小程序商店（minapp.com）：**全网首家小程序商店，已吸引海量小程序入驻，数量仍在不断增长中
- **未来小程序活动矩阵：**包含黑客马拉松、MindTalk 、WorkShop，创造多样的小程序交流分享空间
- **《微信小程序入门指南电子书》：**全网首本小程序电子书**，**已在多看阅读、微信读书、QQ 阅读上架

---

文 \| 一斤代码

事件机制是一种非常典型的通讯方式。有了它，你可以令代码中的不同对象互相传递信息，也可以在应用的不同层面进行沟通协作。

今天我们来看一下微信小程序框架提供的事件处理机制。

小程序官方文档对事件的定义是： 

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

从这里我们可以看到，官方文档主要将事件用于小程序中针对用户交互行为的处理，即视图层（WXML）到逻辑层（Page）的通信，逻辑层收到这些用户行为事件后，可以进行业务处理，然后根据情况反馈或不反馈结果给用户。

好，那我们今天就撇开事件的其他用法，专门就讲视图层和逻辑层之间的事件用法。

### 在视图层绑定事件

总体上来说，小程序中的事件机制在工作原理上来讲，和 HTML DOM 的事件机制是一致的。在 HTML 中，我们可以通过在 HTML 元素上设置一个如 `onclick="clickHandler(event)"` 的属性来绑定用户的页面点击事件处理函数。

而在 WXML 中，我们为一个组件绑定一个事件处理函数，可以使用如下语法来完成：

![1](https://s3.ifanr.com/wp-content/uploads/2017/01/1-44.jpg)

这里的 `bindtap` 就可以理解为将点击事件绑定到一个名为 `tapName` 的事件处理函数上来进行处理。然后在相应的 `Page` 代码中，我们需要定义这个 `tapName` 函数：

![2](https://s3.ifanr.com/wp-content/uploads/2017/01/2-23.jpg)

这样完成了一个简单的点击事件的处理。当我们在小程序的界面上去点击这个显示为 Click me 的 `view` 组件的时候：

- `view` 组件捕获到这个点击动作，然后告诉 `Page` 中的 `tapName` 函数，要对这个动作进行处理；
- 同时，这个组件也为 `tapName` 函数提供了足够多的信息，也就是 `event` 对象，来帮助我们更好更精准的处理我们的业务逻辑。

我们可以来看一下我们这个例子中的 `event` 对象里面包含了哪些内容：

![3](https://s3.ifanr.com/wp-content/uploads/2017/01/3-22.jpg)

这里我们可以看到，在 `event` 对象中，包含了事件的名称，事件目标对象的信息，以及事件发生的在界面上的位置信息等等。

我们在组件上设置的 `data-hi` 属性的值，也在 `target` 中的 `dataset` 上被携带了过来，这是比较有用的。在实际开发中，我们可以利用这个特性，来传递更多视图层的信息到逻辑层进行处理。

### 事件的继承和冒泡

如果你有 DOM 编程的经验，你就会在这里想到，小程序里事件的冒泡和非冒泡是怎么处理的？

如果你还不了解什么是事件冒泡，那我在这里解释一下：

在 HTML 或者 WXML 这些基于 XML 的树形结构的界面布局方式中，元素与元素之间是有层级关系的。

子级元素上触发的事件，可以向父级元素逐层向上传递。所以，父级元素上也可以捕获子级元素上的事件并进行逻辑处理。

这种事件冒泡的机制，在实际的开发中也经常会用到，所以我们有必要来了解下在小程序中，是如何来使用冒泡事件的。WXML 中分别提供了两种方式，用来绑定事件处理函数：

- 使用 `bind` 开头的事件绑定，这种绑定不会阻止冒泡事件向上冒泡；
- 使用 `catch` 开头的事件绑定，这种绑定可以阻止冒泡事件向上冒泡。

直观起见，我们直接来看一个示例代码：

![4](https://s3.ifanr.com/wp-content/uploads/2017/01/4-24.jpg)

![5](https://s3.ifanr.com/wp-content/uploads/2017/01/5-17.jpg)

在这个示例代码中，有三个逐级嵌套的 `view` 元素，最里层的是 `content` 元素，最外层的为 `outer-container` 元素。

最里层和最外层的元素上，使用了 `bind` 属性绑定了 `tap` 事件的处理函数，而中间的 `innner-container` 上，使用了 `catch` 属性进行 `tap` 事件绑定。

然后，我们尝试在 `content` 上点击一下，可以看到这样的结果：

![6](https://s3.ifanr.com/wp-content/uploads/2017/01/6-9.jpg)

`content` 和 `inner-container` 元素的 `tap` 事件处理函数被执行了，而 `outer-container` 元素的没有被执行。这说明在点击 `content` 的过程中，产生的 `tap` 事件向父级元素传递。

而作为 `content` 元素的父级元素 `inner-container`, 它使用了能阻止事件冒泡的 `catch` 方式，所以它在捕获通过冒泡形式过来的子级元素事件并执行事件处理函数后，让该事件停止向上传递。

因此，同样是父级元素的 `outer-contaner`，就不再能收到这个冒泡事件了。

然后，来看一下，在不同层级的元素捕获的 `event` 对象，在数据方面有什么特点：

我们可以看到，在 `content` 的 `tap` 事件处理函数中，`event` 里面的 `target` 和 `currentTarget` 的 `id` 都是 `content`。

![7](https://s3.ifanr.com/wp-content/uploads/2017/01/7-7.jpg)

而在 `inner-container` 中的 `event` 对象里，`target` 的 `id` 为 `content`，而 `currentTarget` 的 `id` 是 `inner-content`。

![8](https://s3.ifanr.com/wp-content/uploads/2017/01/8-9.jpg)

由此我们可以知道，`event` 对象中的 `target` 是事件产生的源头组件，而 `currentTarget` 则是当前捕获这个事件的组件。

`event` 对象中还包含其他一些有用的信息，如 `touches` 和 `changedTouches` 表示一个或多个手指在屏幕上的触摸位置和变动位置等信息，可以用来实现多点触摸的高级手势处理。

最后，关于事件冒泡，有一点是值得注意一下的：在微信小程序中，并不是所有事件都是冒泡的。

比如，官方文档提到，`<canvas>` 组件的触摸事件不可冒泡的。

原文地址：<http://www.jianshu.com/p/6b2005ddfb8f>

**本文由知晓程序授权转载，关注微信号 zxcx0101，回复「1228」获得全网第一本《小程序入门指南》电子书。**

![zxcx-qun](https://s3.ifanr.com/wp-content/uploads/2017/01/zxcx-qun.png)

![zxcx-follow-d](https://s3.ifanr.com/wp-content/uploads/2017/01/zxcx-follow-d-1.jpg)

**知晓程序（微信号 zxcx0101）是爱范儿旗下专注于小程序生态的公众号。我们提供最全面、新鲜的小程序资讯（消息、观点、指南、活动）和服务，在这里你能了解到关于小程序的一切。**
