💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 2.5 事件 [【官方文档1】](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html) [【官方文档2】](https://developers.weixin.qq.com/ebook?action=get_post_info&token=935589521&volumn=1&lang=zh_CN&book=miniprogram&docid=000846df9a03909b0086a50025180a) 在小程序里,把这种“用户在渲染层的行为反馈”以及“组件的部分状态反馈”抽象为渲染层传递给逻辑层的“事件”,如图3-7所示。 :-: ![渲染层产生用户交互事件传递给逻辑层](https://box.kancloud.cn/ef0d7d054006785cd71312ebd99130fb_750x521.png) :-: 图3-7 渲染层产生用户交互事件传递给逻辑层 代码清单3-18 事件处理示例 ~~~ <!-- page.wxml --> <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view> // page.js Page({ tapName: function(event) { console.log(event) } }) ~~~ 1. 组件绑定事件处理函数。wxml文件中,事件是通过`bindtap`这个属性绑定在组件上的。 2. 定义事件处理函数。js文件中,在当前页面的Page构造器中定义对应的事件处理函数`tapName`; 3. 触发事件。当用户点击该view区域时,达到触发条件生成事件`tap`,该事件处理函数tapName会被执行,同时还会收到一个事件对象event。 ### 2.5.1 事件类型和事件对象 组件的事件可以参考其参数说明,详情见[官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/component/ ) 常见的用户事件类型如表3-10所示。 :-: 表3-10 常见的冒泡事件类型 | 类型 | 触发条件 | | --- | --- | | touchstart | 手指触摸动作开始| | touchmove | 手指触摸后移动| | touchcancel | 手指触摸动作被打断,如来电提醒,弹窗| | touchend | 手指触摸动作结束| | tap | 手指触摸后马上离开| | longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发| | longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替)| | transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发| | animationstart | 会在一个 WXSS animation 动画开始时触发| | animationiteration | 会在一个 WXSS animation 一次迭代结束时触发| | animationend | 会在一个 WXSS animation 动画完成时触发| 当事件回调触发的时候,会收到一个事件对象,对象的详细属性如下表所示。 :-: 表3-11 事件对象属性 | 属性 | 类型 | 说明| | --- | ---| ---| | type | String | 事件类型| | timeStamp | Integer | 页面打开到触发事件所经过的毫秒数| | target | Object | 触发事件的组件的一些属性值集合| | currentTarget | Object | 当前组件的一些属性值集合| | detail | Object | 额外的信息| | touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组| | changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组| 这里需要注意的是`target`和`currentTarget`的区别,currentTarget为当前事件所绑定的组件,而target则是触发该事件的源头组件。 :-: 表3-12 target和currentTarget事件对象属性 | 属性 | 类型 | 说明| | --- | ---| ---| | id | String | 当前组件的id| | tagName | String | 当前组件的类型| | dataset | Object | 当前组件上由data-开头的自定义属性组成的集合| :-: 表3-13 touch和changedTouches对象属性 | 属性 | 类型 | 说明| | --- | ---| ---| | identifier | Number | 触摸点的标识符| | pageX, pageY | Number | 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴| | clientX, clientY | Number | 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴| 代码清单3-19 事件对象示例 ~~~HTML <!-- page.wxml --> <view id="outer" catchtap="handleTap"> <view id="inner">点击我</view> </view> ~~~ ~~~JavaScript // page.js Page({ handleTap: function(evt) { // 当点击inner节点时 // evt.target 是inner view组件 // evt.currentTarget 是绑定了handleTap的outer view组件 // evt.type == “tap” // evt.timeStamp == 1542 // evt.detail == {x: 270, y: 63} // evt.touches == [{identifier: 0, pageX: 270, pageY: 63, clientX: 270, clientY: 63}] // evt.changedTouches == [{identifier: 0, pageX: 270, pageY: 63, clientX: 270, clientY: 63}] } }) ~~~ ### 2.5.2 事件绑定与冒泡捕获 事件绑定的写法和组件属性一致,以`key="value"`的形式,其中: 1. **`key`以bind或者catch开头,然后跟上事件的类型**,如`bindtap`、`catchtouchstart`。 自基础库版本1.5.0起,bind和catch后可以紧跟一个冒号,其含义不变,如`bind:tap`、`catch:touchstart`。同时bind和catch前还可以加上`capture-`来表示捕获阶段。 2. **`value`是一个字符串**,需要在对应的页面Page构造器中定义同名的函数,否则触发事件时在控制台会有报错信息。 3. `bind`和`capture-bind`的含义分别代表事件的冒泡阶段和捕获阶段,其触发的顺序如图3-8所示。 :-: ![事件捕获和冒泡触发时序](https://box.kancloud.cn/767707139670f8409eb9d62c13a7c7a1_681x573.png) :-: 图3-8 事件捕获和冒泡触发时序 以下示例中,点击 inner view 会先后调用handleTap1、handleTap2、handleTap3、handleTap4。 代码清单3-20 使用capture-前缀阻止事件的冒泡和捕获 ~~~HTML <view id="outer" bind:tap="handleTap4" capture-bind:tap="handleTap1"> outer view <view id="inner" bind:tap="handleTap3" capture-bind:tap="handleTap2"> inner view </view> </view> ~~~ >bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。 如果将以上代码的capture-bind:tap="handleTap1"改成capture-catch:tap="handleTap1",点击inner view只会触发handleTap1(catch事件阻止了tap事件冒泡)。 代码清单3-21 事件的冒泡和捕获 ~~~HTML <view id="outer" bind:tap="handleTap4" capture-catch:tap="handleTap1"> outer view <view id="inner" bind:tap="handleTap3" capture-bind:tap="handleTap2"> inner view </view> </view> ~~~ 注意,除表3-10列举的事件类型之外的其他组件自定义事件,如无特殊声明都是非冒泡事件,如\<form/>的submit事件,\<input/>的input事件,\<scroll-view/>的scroll事件。