携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
小程序需要经常和用户进行某种交互,比如点击界面上的某个按钮或者区域,比如滑动了某个区域
所以在小程序中经常会触发各种各样的事件
事件可以绑定在组件上,将用户的行为反馈到逻辑层进行处理
当触发事件时,就会执行逻辑层中对应的事件处理函数
事件在被触发时,也会传递事件对象,事件对象可以携带额外信息,如 id, dataset, touches
事件是通过bind/catch这个属性绑定在组件上的
事件名以bind或catch开头, 从1.5.0版本开始, 可以在bind和catch后加上一个冒号
同时在当前页面的Page构造器中定义对应的事件处理函数, 如果没有对应的函数, 触发事件时会报错
绑定事件不需要使用mustache语法, 如果使用了mustache语法会导致对应的事件无法被正常触发
公共事件
以下事件是所有组件都可以触发的事件
某些组件会有自己特性的事件类型, 具体事件可以查看对应的组件文档
- 比如input有bindinput/bindblur/bindfocus等
- 比如scroll-view有bindscrolltowpper/bindscrolltolower等
事件对象
当某个事件触发时, 会产生一个事件对象, 并且这个对象被传入到回调函数中
currentTarget 和 target
<!--
当视图层发生事件时,某些情况需要事件携带一些参数到执行的函数中, 这个时候就可以通过data-属性来完成
-->
<view id="outer" class="outer" data-name="Klaus" bindtap="handleTap">
<view id="inner" class="inner"></view>
</view>
Page({
// 点击div.inner组件后
handleTap(e) {
// target - 实际触发事件的那个组件 - div.inner
console.log(e.target)
// currentTarget - 实际处理事件函数的那个组件 - div.outer
console.log(e.currentTarget)
// 因为target并不一定是处理事件的那个组件,而currentTarget一定是处理事件的那个组件
// 也就是说小程序中的事件是存在冒泡和捕获过程的
// 所以如果我们希望可以正确获取我们传递给事件的那些自定义参数,推荐使用currentTarget来进行获取
console.log(e.currentTarget.dataset.name)
}
})
touches和changedTouches
当刚开始点击的时候,只有一个手指,所以此时touches和changedTouches中对应的值是一致的
但是当一个手指按住不动,在添加第二个和第三个手指的时候,因为新增加了两个手指
所以touches中记录的是所有的手指个数,所以是长度为3的数组
而changedTouches中记录的是改变的手指个数,所以是长度为2的数组
同理,在点击结束手指离开的时候
在touchstart事件中,因为此时点击在屏幕上的手指为一个,且是从零个手指变成一个手指的点击
所以此时touches和changedTouches中的值是一致的,是长度为1的数组
但是在touchend事件中,因为此时点击屏幕的手指由一个转变为了零个手指,
所以此时touches数组为长度为0的数组,而changedTouches为长度为1的数组
参数传递
wxml
<view class="list">
<!-- data-current-tab 在dataset中会被转换为 currentTab -->
<view
wx:for="{{ list }}"
wx:key="*this"
class="item"
data-current-tab="{{ item }}"
bindtap="handleTap">
<text class="{{ item === activeTab ? 'active' : '' }}">{{ item }}</text>
</view>
</view>
wxs
Page({
data: {
list: ['衣服', '裤子', '鞋子'],
activeTab: '衣服'
},
handleTap(e) {
this.setData({
// 获取到的数据 最好通过currentTarget去获取
// 以确保对应的元素为实际处理当前事件的那个元素
activeTab: e.currentTarget.dataset.currentTab
})
}
})
wxss
.list {
display: flex;
align-items: center;
}
.item {
flex: 1;
text-align: center;
}
.item text {
padding-bottom: 6rpx;
display: inline-block;
}
.active {
color: #f99;
border-bottom: 2px solid #f99;
}
mark
使用data-*进行参数传递,在获取参数的时候需要区分currentTarget和target,且获取层级较深
为此自小程序sdk2.7开始,提供了一种新的用于进行参数传递的方式,即mark
<button mark:btnArg="button上传递的参数" bindtap="handleTap">
<text mark:textArg="text上传递的参数">click me</text>
</button>
Page({
handleTap(e) {
// mark的默认值是一个空对象
// mark中会存放所有位于该事件捕获和冒泡流程中所有元素对应的被mark标签的属性
console.log(e.mark) // => {textArg: "text上传递的参数", btnArg: "button上传递的参数"}
}
})
事件冒泡和捕获
- 事件名可以全小写,也可以使用冒号进行拼接,他们之间是没有任何区别的
bindtap === bind:tap
capture-bindtap === caoture-bind:tap
-
bind表示的事件,该事件会正常捕获和冒泡
但是如果使用catch表示该事件会阻止事件的进一步传递
# 该事件可以正常的进行事件冒泡和捕获
bindtap
# 该事件会阻止事件的冒泡
catchtap
# 该事件会阻止事件的捕获
capture-catchtap