赞
踩
最近在做项目的过程中遇到一个非常奇葩的bug,在h5页面点击一个按钮弹出弹窗,但是这个弹窗刚出现就会自动消失,导致屏幕出现闪动现象,关键这个bug还是偶现的。经过一番研究才发现是vue事件点击穿透引起的,而且弹窗一定要在300ms内出现才会引发这个bug,接下来分析具体原因:
vue框架内置指令v-on:click有300ms的延迟响应,这是为了判断区分单击和双击。vue为移动端提供了触摸方法touchstart、touchmove、touchend,但却没有提供tap指令,因此需要自己手动定义v-tap去消除300ms延迟,提升移动端用户体验。
自定义v-tap指令可以参考我之前的文章分别用vue和Android实现长按券码复制功能
看似tap事件完美解决了移动端延迟响应的问题,但是它却有个致命的缺点:touch之后300ms会触发click
回到我上面提到的那个bug,因为我给按钮绑定的是tap事件,而弹窗是click。当我点击按钮弹出弹窗后,刚好在屏幕相同的位置触发了弹窗的click事件,因此弹窗消失。而且一定要在300ms内发生,如果弹窗出现时间较长,大于300ms,则不会出现这个问题,这也就是为什么那个bug是偶现的。
bug隐藏得够深啊,过了好久才想明白
1,v-on:click和v-tap不要混用
还是拿上面那个例子来说明。如果页面里面的元素是v-tap,弹窗是v-on:click则可能出现页面闪动;反之有可能穿透弹窗,引发页面按钮的点击。因为这个时候弹窗消失了,touch300ms后引发的click事件会作用在屏幕相同位置的按钮上。
2,阻止单击事件继续传播
v-on:click.stop
event.stopPropagation() 。 // 对click和touch都适用,但是防不住touch300ms后引发click
3,css中的pointer-events
这个属性确切地说不是用来阻止vue事件点击穿透,而是精确地控制点击事件的响应元素
pointer-events的值有两个:auto / none,auto是默认值,none表明该元素不响应点击事件,该事件继续往下传递
既然本文主要围绕h5页面和弹窗的点击穿透事件讲解,那我顺便分享个滑动穿透的解决技巧。
当h5页面内容较多,一屏展示不下时,在y方向是可以滑动的。这时候如果弹出弹窗,弹窗本身是不可滑动的,但是滑动弹窗,会引发弹窗下面H5页面的滑动。我之前的解决办法是用watch方法,监视弹窗的弹出状态动态设置h5页面的style属性:overflow-y 为auto或者hidden。
后来发现还有更优雅的解决办法,只需要防止弹窗的滑动穿透即可:@touchmove.prevent=""
<div class="right-description" v-show="showPop" @click="closeRightPop" @touchmove.prevent="">
<img src="../../assets/coupon/refund_tip_img.png"/>
</div>
作为一名开发,写出来的代码不仅要满足产品基本需求,还要更优雅简单才好。H5进阶之路还很漫长,共勉…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。