第3章小程序的事件 本章学习目标  理解事件的概念与事件对象的概念,并能进行区分。  熟悉几种常用的事件对象,以及其对应的绑定方式。  了解事件对象的类型。  学会绑定事件以及如何获取事件对象中的数据。  通过实例区别事件对象中的target与currentTarget属性。 3.1事件对象 3.1.1事件与事件对象概述 事件是一种用户行为,用户的点击、滑动等操作都可以成为事件。事件也是一种通信方式,能够完成视图层(WXML页面文件)与逻辑层(JS逻辑文件)之间的通信。 事件对象是指用户在点击、滑动等动作触发后形成的一个带有数据的Object对象,该对象可在组件绑定的逻辑函数中作为参数传入(通常用字母e表示)。在WXML页面文件中,事件绑定到组件上,当事件触发时,就会执行逻辑层中对应的事件处理函数。事件对象可携带额外信息,如id、dataset、touches等数据,后续可在函数中获取相应的数据进行操作。 例如2.2.7节数据绑定综合案例中关于按钮的点击事件,首先button组件需要利用bindtap属性绑定对应的事件处理函数。除此之外,还可以利用“data*”的形式在该组件上绑定数据,其中*号的意思是用户需自定义数据的变量名,这些数据可携带在事件对象中传入事件处理函数。 3.1.2事件对象分类 事件对象可以分为基础事件(BaseEvent)、自定义事件(CustomEvent)和触摸事件(TouchEvent)。其中后两个均继承自基础事件,即完整地拥有父类的全部属性。 1. 基础事件 基础事件具体说明如表31所示。 表31基础事件对象类型及其属性列表 属性 类型 说明 type string 事件类型 timeStamp integer 事件生成时的时间戳 target object 触发事件的组件的一些属性值集合 currentTarget object 当前组件的一些属性值集合 2. 自定义事件 自定义事件继承自基础事件,即包含基础事件的所有属性,此外还有detail属性,具体说明如表32所示。 表32自定义事件对象类型及其属性列表 属性 类型 说明 detail object 额外的信息 3. 触摸事件 触摸事件继承自基础事件,即包含基础事件的所有属性,此外还有touches和changedTouches属性,具体说明如表33所示。 表33触摸事件对象类型及其属性列表 属性 类型 说明 touches array 触摸事件,当前停留在屏幕中的触摸点信息的数组 changedTouches array 触摸事件,当前变化的触摸点信息的数组 4. target与currentTarget 在事件对象中,比较重要的属性是target与currentTarget,二者的子属性完全一样,如表34所示。 表34target与currentTarget的属性 属性 类型 说明 id string target中为事件源组件的id,currentTarget中为当前组件的id dataset object 当前组件中以data开头的自定义属性组成的集合 由于事件有冒泡与非冒泡之分,因此绑定了事件的组件与发生事件的组件并不一定相同,currentTarget代指绑定了事件的组件,而target指的是发生了事件的组件,关于二者的区别可参考3.3.2节事件绑定案例更深刻地理解。 视频讲解 3.1.3事件对象打印案例 1. 实现效果 本节将结合前两节所学的关于事件对象的知识,编写不同事件对象的打印输出案例,在观察输出时需注意type属性区分不同事件对象,以及事件对象中携带数据的位置等。案例实现效果如图31所示。 图31事件对象打印案例实现效果 2. WXML页面代码 新建项目Chapter03与eventObject页面,WXML页面代码如下: 1.!--pages/demo3-1/eventObject.wxml-- 2.view class='container' 3.view class='page-body' 4.text class='h1'事件对象的打印案例/text 5.view class='demo-box' 6.view class="title"按钮点击事件bindtap/view 7.button type="primary" bindtap="printEvent" data-info="这是绑定的数据" 8.点击打印 9./button 10./view 11.view class='demo-box' 12.view class="title"触摸事件对象的打印/view 13.view class="touch-view" bindtouchstart="printEvent" bindtouchend="printEvent" 请触摸当前视图 /view 14./view 15.view class='demo-box' 16.view class="title"内容输出区域/view 17.text class="content"{{content}}/text 18./view 19./view 20./view 3. JS代码 JS文件中printEvent事件处理函数代码如下: 1.// pages/demo3-1/eventObject.js 2.printEvent: function(e) { 3.console.log(e) //打印事件对象 4.var eventObjStr=JSON.stringify(e) 5.this.setData({ content: eventObjStr}) 6.}, 在Console面板中可看到打印完整的事件对象,展开内容前面的灰色三角箭头即可看到详细属性,该对象包括type、timeStamp、target、currentTarget等属性,而刚刚利用datainfo="这是绑定的数据"写入事件对象的info变量可以在e.currentTarget.dataset.info中获取到。 关于data*自定义数据还要注意的是,若写成databtninfo="data ",即多个“”符号连接,最终会强制转换为驼峰标记法(又称为Camel标记法,特点是第一个单词全部小写,后面每个单词只有首字母大写),即得到的数据为: { btnInfo: " data " }; 若写成databtnInfo,即一个变量名里有大写字母,最终会强制转为小写字母,即得到的数据为: { btninfo: " data " }。建议在开发过程中,如果要使用事件对象可以打印出来,在调试窗口确认变量名后再使用,以免出错。 3.2事件类型 在小程序中,事件分为两大类型: (1) 冒泡事件,当一个组件上的事件被触发后,该事件会向父节点传递。 (2) 非冒泡事件,当一个组件上的事件被触发后,该事件不会向父节点传递。 3.2.1冒泡事件 组件上的冒泡事件被触发后,该事件会向父节点传递。在3.1.3节事件对象打印案例中小程序中使用了tap、touchstart和touchend事件对象,这些都属于冒泡事件,小程序提供的全部冒泡事件如表35所示。 表35冒泡事件 类型 触 发 条 件 touchstart 手指触摸动作开始 touchmove 手指触摸后移动 touchcancel 手指触摸动作被打断,如来电提醒、弹窗 touchend 手指触摸动作结束 tap 点击事件,手指触摸后马上离开 longpress 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发(最低版本1.5.0) longtap 长按事件,手指触摸超350ms再离开(推荐用longpress事件代替) transitionend 会在WXSS transition或wx.createAnimation动画结束后触发 animationstart 会在一个WXSS animation动画开始时触发 animationiteration 会在一个WXSS animation一次迭代结束时触发 animationend 会在一个WXSS animation动画完成时触发 touchforcechange 在支持3D Touch的iPhone设备,重按时会触发(最低版本1.9.90) 除表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,例如表单(form)的提交事件、输入框(input)的输入事件等,具体使用可参见第10章对应组件属性说明。 视频讲解 3.2.2冒泡事件案例 1. 运行效果 冒泡事件的具体案例运行效果如图32所示。点击图32(a)中的view 3,控制器输出情况如图32(b)所示。 图32冒泡事件测试 2. WXML代码 新建页面bubblingEvent,页面的WXML代码如下: 1.!--pages/demo3-2/ bubblingEvent.wxml-- 2.view class='container' 3.view class='page-body' 4.text class='h1'冒泡事件案例/text 5.view class='demo-box' 6.view class="title"冒泡事件/view 7.view class="content"请分别点击不同view,观察控制器输出/view 8.view class="view1" bindtap="view1click" 9.view 1 10.view class="view2" bindtap="view2click" 11.view 2 12.view class="view3" bindtap="view3click" 13.view 3 14./view 15./view 16./view 17./view 18./view 19./view 3. JS代码 JS代码主要是三个简单的打印输出函数,具体如下: 1.!--pages/demo3-2/ bubblingEvent.wxml-- 2.Page({ 3.view1click:function(){ 4.console.log("view1click") 5.}, 6.view2click: function () { console.log("view2click") }, 7.view3click: function () { console.log("view3click") }, 8.}) 3.3事件绑定类型 3.3.1阻止冒泡事件 前面讲到的事件绑定都是bind开头,而英文bind与中文“绑定”也是谐音,会让人误以为事件绑定即使用bind*开头的属性即可,其实不然,事件绑定分别有bind与catch两种,两者的区别如下: bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。其中bindtap的方式已经通过3.2.1节的案例初步了解,接下来将通过修改该案例帮助理解catchtap阻止冒泡。 (1) 修改bindtap为catchtap,代码如下所示: 1.view class="view1" bindtap="view1click" 2.View 1 3.view class="view2" catchtap="view2click" 4.!--catchtap可阻止事件继续冒泡-- 5.view 2 6.view class="view3" bindtap="view3click" 7.view 3 8./view 9./view 10./view (2) 保存后再次点击view 3,可看到日志只会输出view3click与view2click,说明冒泡事件被阻止,如图33所示。 图33catchtap阻止事件继续冒泡 3.3.2target与currentTarget的区别 1. 完善案例的WXML代码 在3.3.1节的基础上继续完善案例以便更深刻地理解事件对象中的target与currentTarget的区别。首先给bubblingEvent.wxml的三个view添加上id属性,示例代码如下所示: 1.view class="view1" id="v1" bindtap="view1click" 2.view 1 3.view class="view2" id="v2" catchtap="view2click" 4.!-- catchtap可阻止事件继续冒泡 -- 5.view 2 6.view class="view3" id="v3" bindtap="view3click" 7.view 3 8./view 9./view 10./view 2. JS打印该对象 在JS文件中对应的事件处理函数中传入事件对象,并打印该对象。示例代码如下所示: 1.Page({ 2.view1click:function(e){ 3.console.log(e, "view1click") 4.}, 5.view2click: function (e) { console.log(e, "view2click") }, 6.view3click: function (e) { console.log(e, "view3click") }, 7.}) 3. 实现效果说明 target指触发事件的组件的一些属性值集合,currentTarget指当前组件的一些属性值集合。现点击最内层的view 3,冒泡事件会进行到view 2,可在控制台看到打印的两个事件对象,第一个是id为v3的view 3组件,其绑定事件的组件与发生事件的组件都是view 3。而冒泡事件传递到view 2时,同样触发view 2对应的事件处理函数,其打印的事件对象显示发生事件的组件是view 2,但触发的组件id却是v3,即target属性内的id显示为v3。控制器具体输出效果如图34所示。 图34target与currentTarget的区别 3.4本章小结 本章主要围绕小程序中的事件讲了3部分内容。第1部分是事件对象,要能区别事件与事件对象的概念,并了解事件对象有哪些分类和常用的属性。通过3.1.3节事件对象打印案例的学习能够对事件对象有一个更直观的理解。第2部分讲了事件的两大类型: 冒泡与非冒泡,只需记住一些冒泡的特例即可,通过3.2.2节的冒泡事件案例能够直观理解冒泡事件的传递过程。第3部分是事件绑定的两种类型bind与catch,catch能够阻止冒泡,通过3.3.1节对于案例的改写将有具体的了解。在事件对象中,以data*开头绑定的数据往往藏在target与currentTarget两个属性中,因此通过3.3.2节的案例改写将帮助更好地理解二者的区别。总之,通过本章的学习,应当对事件对象、事件类型有基本的认识,并能学会其基本使用方法。