目录
1、事件处理简述
小程序需要经常和用户进行某种交互,比如点击界面上的某个按钮或区域、或页面滑动,这些交互都会产生各种各样的事件;
事件是通过 bind/catch 属性 绑定在组件上的,和普通的属性写法相似,比如:<button bindtap='tapName'>按钮</button>,都是以 key = "value" 形式。同时在当前页面对应的 .js 文件中的 Page 构造器内定义对应的事件处理函数 tapName,如果没有对应的函数,触发事件时会报错。当用户点击该 button 区域时,达到触发条件生成事件 tap,该事件处理函数 tapName 全被执行,同时还会收到一个事件对象 event。
<button bindtap='handleBtnClick' size='mini'>按钮</button> <!--需要到js文件中定义handleBtnClick()函数-->
<button bind:tap='handleBtnClick' size='mini'>按钮</button> <!--还可在 bind 或 catch 后加上一个冒号-->
<button catch:tap='handleBtnclick'size='mini'>按钮</button> <!--除了使用bind属性,还可以使用catch属性绑定事件-->
2、常见的事件类型
某些组件会有自己特性的事件类型,大家可以在使用组件时具体查看对应的文档,比如 input 有 bindinput/bindblur/bindfocus 等,scroll-view 有 bindscrolltowpper/bindscrolltolower 等,这里我们讨论一下几个组件都有的,并且也比较常见的事件类型:
类型 | 触发条件 |
touchstart | 手指触摸动作开始 |
touchmove | 手指触摸后移 |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 |
touchend | 手指触摸动作结束 |
tap | 手指触摸后马上离开 |
longpress | 手指触摸后,超过 350ms 再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发 |
longtap | 手指触摸后,超过 350ms 再离开(推荐使用 longpress 事件代替) |
<!--常见的一些事件,这些事件都需要到 .js 文件中定义,而且这些事件可以接收一个 event 参数-->
<view class='box'
bind:touchstart="handleTogchStart"
bind:touchmove="handleTouchMove"
bind:touchend="handleTouchEnd"
bind:tap="handleTap"
bind:longpress="handleLongpress"></view>
注意:Touchcancle:在某些特定场景下才会触发(比如来电打断)、tap 事件和 longpress 事件通常只会触发其中一个
3、事件对象的解析
当某个事件触发时,会产生一个事件对象,并且这个对象被传入到回调函数中,事件对象有哪些常见的属性?
<button size='mini' bindtap='handleEventclick'>事件对象</button>
<!--.js文件中的Page构造器内对handleEventclick()函数进行定义-->
handleEventclick(event){
console.log(event); <!--会打印出事件对象的属性,具体如下表-->
}
属性 | 类型 | 说明 |
type | String | 事件类型,如:tap、touchstart、touchend |
timeStamp | Integer | 页面打开到触发事件所经过的毫秒数 |
target | Object | 触发事件的组件的一些属性值集合 { id、 offsetTop ... } |
currentTarget | Object | 当前组件的一些属性值集合 |
detail | Object | 额外的信息,记录鼠标点击的位置 { x:... y:... } |
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 [多根手指触摸的位置信息的数组 ] |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
注:(1)touches 和 changedTouches 的区别:touches 是用来记录当前有几个手指在小程序中触摸的,以及对应的触摸点信息。changedTouches 记录变化的手指,比如一开始在小程序中有一根手指在触摸的过程中,又加了一根手指,则 changedTouches 的数组长度为 1,touches 的数组长度为 2。
(2)target 和 currentTarget 的区别:这两个属性在事件冒泡的时候会有不同,target 会记录产生事件的元素,currentTarget 会记录触发事件的元素。比如两个盒子(inner 和 outer),当点击内层盒子时,外层盒子也会触发相应的点击事件,此时 target 记录的就是 inner盒子,而 currentTarget 记录的是 outer 盒子。
4、事件的参数传递
小程序在事件的参数传递上和 vue 不同,vue 可以直接给被点击的组件绑定一个函数,将需要传递的参数放在函数的实参位置上即可,小程序这样传值是不行的。小程序的参数传递需要借助 data- 属性,这样即可在绑定的事件的 event 参数中的 target 和 currentTarget 属性下产生一个 dataset 对象,对象中包含传递过来的参数。
<view class='container'>
<block wx:for="{{titles}}" wx:key="{{index}}"> <!--titles是定义在.js文件中的数组-->
<view bindtap='handleItemClick' data-index="{{index}}" data-item="{{item}}" >{{item}}</view>
</block>
</view>
<!--.js文件中的Page构造器中的代码-->
handleItemClick(event){
console.log(event)
const dataset = event.currentTarget.dataset;
const title = dataset.item;
const index = dataset.index;
console.log(title, index);
}
5、事件冒泡和捕获
当界面产生一个事件时,事件分为了捕获阶段和冒泡阶段。事件由内向外触发为事件冒泡,事件由外向内触发为事件捕获。事件分为冒泡事件和非冒泡事件:1、冒泡事件(bind):当一个组件上的事件被触发后,该事件会向父节点传递。2、非冒泡事件(catch):当一个组件上的事件被触发后,该事件不会向父节点传递。
<!--bind:一层层传递,从view3->view2->view1进行捕获,再view1->view2->view3进行冒泡-->
<view class='view1' capture-bind:tap="handleCaptureview1" bindtap='handleBindviewl'>
<view class='view2' capture-bind:tap="handleCaptureview2" bindtap='handleBindView2'>
<view class='view3' capture-bind:tap="handleCaptureview3" bindtap='handlesindView3'></view>
</view>
</view>
<!--catch:阻止事件的进一步传递,比如将view1的capture-bind改为capture-catch,则只会执行handleCaptureview1()-->
<view class='view1' capture-catch:tap="handleCaptureview1" bindtap='handleBindviewl'>
<view class='view2' capture-bind:tap="handleCaptureview2" bindtap='handleBindView2'>
<view class='view3' capture-bind:tap="handleCaptureview3" bindtap='handlesindView3'></view>
</view>
</view>
<!--catch可以代替以上任意位置的bind,简单的说,它的作用就是让事件执行到自己时停止,不在继续向下捕获或冒泡-->