艺灵设计

全部文章
×

微信小程序从入坑到放弃二十九:一个小场景搞懂冒泡事件bindtap和catchtap的区别

作者:艺灵设计 - 来源:http://www.yilingsj.com - 发布时间:2020-06-05 14:47:59 - 阅: - 评:0 - 积分:0

摘要:在微信小程序中,bindtap事件会产生冒泡,若不加以拦截,会一直冒泡到顶端。在某些情况下,一次点击会触发若干点击事件。为了防止冒泡,使用catchtap即可解决问题。在有全屏半透明背景的弹出层效果中,可以使用catchtouchmove来阻止页面滚动发生穿透。

一、起因

昨天下午,微信上一个近半年未联系的好友突然发消息问我问题。如图:昨天一好友在微信上问问题.png昨天一好友在微信上问问题近一步沟通过后,了解了她的需求。大白话就是:点击非红框框区域时隐藏这个框框。

二、相关知识点

她的这个需求实际上跟弹出层差不多,点击非操作区域时都隐藏功能。这里有两个知识点:
1、事件冒泡;
2、页面滚动穿透(遮罩层背景时用到,此处顺带提一笔)。
微信小程序项目开发中,事件冒泡是家常便饭,也略有小坑。废话不多说,直接上代码。

三、实战代码

为了更直观的复现问题,暂时不封装组件,直接在/index/index.wxml页面中写代码

3.1、项目文件列表

  1. 微信小程序项目根目录
  2.   index /* 项目首页 */
  3.     index.wxml /* 模板页 */
  4.     index.js /* js */
  5.     index.wxss /* 样式文件 */
  6.     index.json /* 配置文件 */
  7.   ...... /* 其他文件 */

3.2、文件中的代码

  1. <view class="page" catchtap="handleCatchTap" bindtouchmove="handleTouchmove">
  2.   <view class="page-content">页面内容区</view>
  3.   <view class="pinglun-info">
  4.     <view class="pinglun__time">23小时前<view class="pinglun__delete">删除</view>
  5.   </view>
  6.     <view class="pinglun-tool" catchtap="handleShowPingLun">
  7.       <view class="pinglun-button">...</view>
  8.       <view class="pinglun-lists \{\{isShow ? 'is__show' : ''\}\}">
  9.         <view class="pinglun__link">取消</view>
  10.         <view class="pinglun__link">评论</view>
  11.       </view>
  12.     </view>
  13.   </view>
  14. </view>

友情提示:上面代码中的\反斜线是为了防止在文章中转码,看官复制后替换为空即可。

  1. var app = getApp();
  2. Page({
  3.   data: {
  4.     isShow: false /* 弹窗显隐 */
  5.   },
  6.   onLoad: function () {},
  7.   /* 点击时显示弹出评论功能 */
  8.   handleShowPingLun() {
  9.     this.setData({
  10.       isShow: !this.data.isShow
  11.     })
  12.   },
  13.   /* 禁止向上冒泡(非操作区域时关闭弹窗) */
  14.   handleCatchTap() {
  15.     if (this.data.isShow) {
  16.       this.setData({
  17.         isShow: false
  18.       })
  19.     }
  20.   },
  21.   /* 滑屏(页面滚动时也关闭弹窗) */
  22.   handleTouchmove() {
  23.     this.handleCatchTap()
  24.   }
  25. });

wxss的代码就不写了,注意上面黄色高亮的事件,这是实现功能的关键!

3.3、为什么是catchtap而不是bindtap?

首先我们看最里面的事件:catchtap="handleShowPingLun",可能很多看官这里会把catchtap写成bindtap。如果这里写成了bindtap,那么当用户点击时,事件会正常一层层向上冒泡,一直冒到当前代码的最外层,也就是view.page这个标签上。当用户在view.page上也添加了tap点击事件时,此时一次点击就会至少触发两次点击。若是这样,我们的业务代码就极有可能存在隐藏bug!当向上的层级树上也有tap点击事件时,此时一次点击就会触若干其他的功能,后果不堪设想!如图:点击评论按钮后事件冒到了顶层并触发了这条线路上的其他点击事件.png点击评论按钮后事件冒到了顶层并触发了这条线路上的其他点击事件

为了防止事件向上冒泡,触发不必要的功能,我们可以把bindtap改为catchtap,也就是示例代码那样,现在我们再来点击看控制台的打印情况。如图:catchtap成功阻止事件向上冒泡.pngcatchtap成功阻止事件向上冒泡

同理,view.pinglun-tool的子级view.pinglun__link也要进行冒泡拦截,就是把bindtap改为catchtap。至于原因,仔细回味下上面几张配图应该能理解。

关于事件,请参见微信官方文档的描述:事件的使用方式

最后我们来看一个gif动图演示,如图:catchtap成功阻止事件向上冒泡.gifcatchtap成功阻止事件向上冒泡怎么样,功能已经实现了,那是不是就结束了呢?

3.4、catchtouchmove解决页面滑动时防穿透

事情并没有至此结束。虽然我们已经做到了点击非评论弹层区域时隐藏弹层的功能,但页面滚动时呢???所以,我们还需要解决页面滚动时的情况。这时,bindtouchmovecatchtouchmove就出场了,具体使用哪个也要看实际的场景。若项目中有一个弹层且带有全屏的半透明背景,那就需要使用catch来禁止页面滚动。示例参见文章:
微信小程序从入坑到放弃二十二:完美兼容安卓和ios手机的底部评论框。本文这里可以使用bind,也就是bindtouchmove

现在,我们算是大功告成了。在实际项目中,评论弹层通常会被封装成一个组件,那么此时的防冒泡处理和滑屏处理就需要写在父级组件或根组件中,具体怎样要看开发者的代码构造。

四、demo源码

demo源码已上传到了github上,如果看官需要研究源码,可以点击下面的链接进行访问并下载。

  1. 源码分支: dev-bindtap-and-catchtap-20200605

源码中会有必要注释和本篇文章中的示例。若有疑问可与艺灵联系,方式见下方二维码或右侧。

转载声明:
  若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:/xwzj/2020-06-05/weixin-bindtap-and-catchtap.html

若亲不想直保留地址,含蓄保留也行。艺灵不想再看到有人拿我的技术文章到他的地盘或者是其它平台做教(装)程(B)而不留下我的痕迹。文章你可以随便转载,随便修改,但请尊重艺灵的劳动成果!谢谢理解。

亲,扫个码支持一下艺灵呗~
如果您觉得本文的内容对您有所帮助,您可以用支付宝打赏下艺灵哦!

Tag: 微信小程序 小程序教程 事件冒泡 防冒泡 页面滚动穿透 catchtouchmove catchtap bindtap 弹出层

上一篇: gulp实战技巧之日常开发定位样式难?不如试试神器gulp-sourcemaps吧!   下一篇: 微信小程序从入坑到放弃三十:wx.pageScrollTo在评论功能中的应用

评论区