事件
DOM 事件
DOM 事件被发送用于通知代码相关的事情已经发生了。每个事件都是继承自
Event
类的对象,可以包括自定义的成员属性及函数用于获取事件发生时相关的更多信息。事件可以表示从基本用户交互到渲染模型中发生的事件的自动通知的所有内容。
小程序事件
小程序是没有DOM的 官方-小程序没有 DOM 接口,原因竟然是……? 事件文档 官方文档
- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches。
使用方式
bindtap
bind:tap
bindtap 等同于bind:tap;
自基础库版本 1.5.0 起,在大多数组件和自定义组件中,bind
后可以紧跟一个冒号,其含义不变,如bind:tap
。基础库版本 2.8.1 起,在所有组件中开始提供这个支持。
<view class="item" bindtap="bindtap" data-type='bindtap'>bindtap</view>
<view class="item" bind:tap='bindtap' data-type='bind:tap'>bind:tap</view>
// 页面的 this.data.handlerName 必须是一个字符串,指定事件处理函数名;如果它是个空字符串,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)。
<view class="item" data-type="handler" bindtap="{{handlerName}}"> handlerName </view>
<view class="item" bindtap="disableHandler"> handlerName方法开关 </view>
Page({
data: {
handlerName: 'handlerName'
},
onLoad: function () {},
bindtap(e){
let type = e.currentTarget.dataset.type;
wx.showToast({
title: `我被点击了,类型是${type}`,
icon: 'none'
})
},
handlerName(e){
let type = e.currentTarget.dataset.type;
wx.showToast({
title: `我被点击了,类型是${type}`,
icon: 'none'
})
},
disableHandler(){
let handlerName = this.data.handlerName;
handlerName.length == 0
? handlerName = 'handlerName'
: handlerName = ''
this.setData({
handlerName: handlerName
},()=>{
handlerName.length == 0
? wx.showToast({
title: `禁用handlerName方法`,
icon: 'none'
})
: wx.showToast({
title: `启用handlerName方法`,
icon: 'none'
})
})
}
})
事件分类
事件分为冒泡事件和非冒泡事件:
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
bind
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
catch
互斥事件 mut-bind
自基础库版本 2.8.2 起,除
bind
和catch
外,还可以使用mut-bind
来绑定事件。一个mut-bind
触发后,如果事件冒泡到其他节点上,其他节点上的mut-bind
绑定函数不会被触发,但bind
绑定函数和catch
绑定函数依旧会被触发。
换而言之,所有mut-bind
是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响bind
和catch
的绑定效果。ps: 这个还没有遇到过使用场景, 直接抄官方demo
// 点击 inner view 会先后调用 handleTap3 和 handleTap2
// 点击 middle view 会调用 handleTap2 和 handleTap1 。
<view id="outer" mut-bind:tap="handleTap1">
outer view
<view id="middle" bindtap="handleTap2">
middle view
<view id="inner" mut-bind:tap="handleTap3">
inner view
</view>
</view>
</view>
事件的捕获阶段
项目中没有使用,只贴一下介绍。详情看官方文档。
自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bind
、capture-catch
关键字,后者将中断捕获阶段和取消冒泡阶段
事件对象
当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。
属性 | 类型 | 说明 | 等级 | 基础库版本 |
---|---|---|---|---|
type | String | 事件类型 | 🌟 | |
timeStamp | Integer | 事件生成时的时间戳 | 🌟 | |
target | Object | 触发事件的组件的一些属性值集合 | 🌟🌟🌟 | |
currentTarget | Object | 当前组件的一些属性值集合 | 🌟🌟🌟 | |
mark | Object | 事件标记数据 | 🌟🌟🌟 | 2.7.1 |
target
触发事件的源组件。就是你点谁了。
属性 | 类型 | 说明 |
---|---|---|
id | String | 事件源组件的id |
dataset | Object | 事件源组件上由data- 开头的自定义属性组成的集合 |
dataset
在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
在 WXML 中,这些自定义数据以 data-
开头,多个单词由连字符 -
连接。
这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:
data-element-type
,最终会呈现为event.currentTarget.dataset.elementType
;data-elementType
,最终会呈现为event.currentTarget.dataset.elementtype
。
连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符
连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符
连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符
重要的事情说三遍 👆
mark
没有关注文档,不知到何时偷偷更新的小可爱 mark
在基础库版本 2.7.1 以上,可以使用
mark
来识别具体触发事件的 target 节点。此外,mark
还可以用于承载一些自定义数据(类似于dataset
)。
当事件触发时,事件冒泡路径上所有的mark
会被合并,并返回给事件回调函数。(即使事件不是冒泡事件,也会mark
。)
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>
// 如果按钮被点击,将触发 bindViewTap 和 bindButtonTap 两个事件。
// 事件携带的 event.mark 将包含 myMark 和 anotherMark 两项
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
区别
mark
会包含从触发事件的节点到根节点上所有的mark:
属性值;- 存在同名的
mark
,父节点的mark
会被子节点覆盖。 - 在自定义组件中接收事件时,
mark
不包含自定义组件外的节点的mark
dataset
仅包含一个节点的data-
属性值;mark
不会做连字符和大小写转换;
detail
自定义事件所携带的数据,如表单组件的提交事件会携带用户的输入,媒体的错误事件会携带错误信息。
bindKeyInput: function (e) {
this.setData({
inputValue: e.detail.value
})
}
小结
事件应该是前端基本的入门操作,但是小程序和其他框架实现有所不同,文档还是要认真阅读的。比如 dataset
连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符,没有仔细看文档的话第一次遇到一脸懵。又比如新增 mark
互斥事件 这些不是很常用但是很有效的方法。
笔记写的不错
先赞再看。
先点后看。有个问题啊,小程序的话,我如何获得元素的offsetWidth?
先点再看