Appearance
事件的监听
什么时候会产生事件呢?
小程序需要经常和用户进行某种交互,比如点击界面上的某个按钮或者区域,比如滑动了某个区域;
事件是视图层到逻辑层的通讯方式;
事件可以将用户的行为反馈到逻辑层进行处理;
事件可以绑定在组件上,当触发事件时,就会执行逻辑层中对应的事件处理函数;
事件对象可以携带额外信息,如 id, dataset, touches;
事件时如何处理呢?
事件是通过bind/catch这个属性绑定在组件上的(和普通的属性写法很相似, 以key=“value”形式);
key以bind或catch开头, 从1.5.0版本开始, 可以在bind和catch后加上一个冒号;
同时在当前页面的Page构造器中定义对应的事件处理函数, 如果没有对应的函数, 触发事件时会报错;
比如当用户点击该button区域时,达到触发条件生成事件tap,该事件处理函数会被执行,同时还会收到一个事件对象event。
html
<!-- 1.事件的基本使用 -->
<button bindtap="onBtnTap">按钮</button>javascript
Page({
// 绑定事件监听函数
onBtnTap(event) {
console.log("onBtnTap:", event);
},
})组件的特殊事件
某些组件会有自己特性的事件类型,大家可以在使用组件时具体查看对应的文档
比如input有bindinput/bindblur/bindfocus等
比如scroll-view有bindscrolltoupper/bindscrolltolower等
这里我们讨论几个组件都有的, 并且也比较常见的事件类型:

事件对象event
当某个事件触发时, 会产生一个事件对象, 并且这个对象被传入到回调函数中, 事件对象有哪些常见的属性呢?

currentTarget和target的区别
html
<!-- 2.event中target和currentTarget区别 -->
<view id="outer" class="outer" data-name="why" bindtap="onOuterViewTap">
<view id="inner" class="inner"></view>
</view>javascript
Page({
onOuterViewTap(event) {
// 1.target触发事件的元素
// 2.currentTarget处理事件的元素
console.log("onOuterViewTap:", event);
console.log(event.target);
console.log(event.currentTarget);
// 3.获取自定义属性: name
const name = event.currentTarget.dataset.name
console.log(name);
},
})touches和changedTouches的区别
1.在touchend中不同

2.多手指触摸时不同

刚开始按住一个手指不放,后面又按了2个手指。
html
<!-- 3.event中touches和changeTouches区别 -->
<view
class="touches"
bindtap="onTouchTap"
bindlongpress="onLongPress"
bindtouchend="onTouchEnd"
>
多指触摸
</view>javascript
Page({
// 监听触摸事件
onTouchTap(event) {
console.log("tap:", event);
},
onLongPress(event) {
console.log("long:", event);
},
onTouchEnd(event) {
console.log("end:", event);
},
})事件参数的传递
当视图层发生事件时,某些情况需要事件携带一些参数到执行的函数中, 这个时候就可以通过data-属性来完成:
格式:data-属性的名称
获取:e.currentTarget.dataset.属性的名称
html
<!-- 4.event的参数传递 -->
<view
class="arguments"
bindtap="onArgumentsTap"
data-name="why"
data-age="18"
data-height="1.88"
>
参数传递
</view>javascript
Page({
// 监听事件, 并且传递参数
onArgumentsTap(event) {
console.log("onArgumentsTap:", event);
const { name, age, height } = event.currentTarget.dataset
console.log(name, age, height);
},
})参数传递的案例练习
html
<!-- 5.tab-control案例(重要) -->
<view class="tab-control">
<block wx:for="{{ titles }}" wx:key="*this">
<view
class="item {{index === currentIndex ? 'active': ''}}"
bindtap="onItemTap"
data-index="{{index}}"
>
<text class="title">{{ item }}</text>
</view>
</block>
</view>javascript
Page({
data: {
titles: ["手机", "电脑", "iPad", "相机"],
currentIndex: 0
},
onItemTap(event) {
const currentIndex = event.currentTarget.dataset.index
console.log(currentIndex);
this.setData({ currentIndex })
},
})css
/* tab-control */
.tab-control {
display: flex;
height: 40px;
line-height: 40px;
text-align: center;
}
.tab-control .item {
flex: 1;
}
.tab-control .item.active {
color: #ff8189;
}
.tab-control .item.active .title {
border-bottom: 3px solid #ff8189;
padding: 5px;
}事件冒泡和事件捕获
当界面产生一个事件时,事件分为了捕获阶段和冒泡阶段。
先触发事件捕获,这是从外向内,再触发事件冒泡,这是从内向外。

html
<!-- 6.捕获和冒泡阶段 -->
<view class="view1" capture-bind:tap="onView1CaptureTap" bindtap="onView1Tap">
<view class="view2" capture-bind:tap="onView2CaptureTap" bindtap="onView2Tap">
<view class="view3" capture-bind:tap="onView3CaptureTap" bindtap="onView3Tap"></view>
</view>
</view>javascript
Page({
// 捕获和冒泡过程
onView1CaptureTap() {
console.log("onView1CaptureTap");
},
onView2CaptureTap() {
console.log("onView2CaptureTap");
},
onView3CaptureTap() {
console.log("onView3CaptureTap");
},
onView1Tap() {
console.log("onView1Tap");
},
onView2Tap() {
console.log("onView2Tap");
},
onView3Tap() {
console.log("onView3Tap");
},
})html
<!-- 7.将bind替换为catch: 阻止事件仅一步传递(了解) -->
<!-- 只会打印 onView1CaptureTap 和 onView2CaptureTap -->
<view class="view1" capture-bind:tap="onView1CaptureTap" bindtap="onView1Tap">
<view class="view2" capture-catch:tap="onView2CaptureTap" bindtap="onView2Tap">
<view class="view3" capture-bind:tap="onView3CaptureTap" bindtap="onView3Tap"></view>
</view>
</view>给逻辑传递数据的另一种方式:mark
html
<!-- 8.给逻辑传递数据, 另外一种方式: mark -->
<view
class="mark"
bindtap="onMarkTap"
data-name="why"
data-age="18"
mark:name="kobe"
mark:age="30"
>
<text mark:address="洛杉矶" class="title">mark</text>
</view>javascript
Page({
// mark的数据传递
onMarkTap(event) {
console.log(event);
const data1 = event.target.dataset
console.log(data1);
const data2 = event.mark
console.log(data2);
}
})