移动页面点击击穿问题
问题
在移动端,click 事件有 300ms 的延迟,当 touchend 事件把上层元素隐藏之后,隔了300ms,浏览器触发了 click 事件,但是此时上层元素不见了,所以该事件被派发到了下层元素身上。如果下层对应的元素是一个链接,那页面就会意外地跳转,如果下层元素绑定了其他事件,此时更会有出乎意料的事情发生。
解决
我们项目当中使用的antd推荐的Fastclick插件,意图解决300ms点击延迟问题,但实际开发当中,发现仍然存在点击穿透的情况(遮罩上方选择学校,遮罩消失之后对应下方的书籍卡片被意外点击,并展示了书籍中的乐谱信息。。。满眼的列表项),起初为了尽快解决问题,在遮罩下方又加了一层透明遮罩绑定click事件(点击消失)当肉盾,事后整理如下:
- fastclick使用touchend事件模拟click触发,并将真正的click事件屏蔽掉,但在某些(Android)手机上仍然存在不能屏蔽原生click事件的bug,造成点击事件触发两次的问题。
跨页穿透问题解决方案:
1234567#preventClick { width:100%; height:100%; position:absolute; z-index:1000; top:0; left:0; }<body><div id="preventClick"></div></body>function onDeviceReady() {setTimeout(function(){ $('#preventClick').hide(); }, 300);}本页穿透解决方案:
12345678910#preventClick { width:100%; height:100%; position:absolute; z-index:999; top:0; left:0; }<container><div class='mask'></div><div id="preventClick"></div></container><script>document.getElementById('preventClick').onclick=function(e){e.target.style.display="none";};</script>由于穿透事件是click延迟造成的,只要将click事件用touch或者tap(由Zepto或KISSY库提供,同样由touch模拟出来的。)
总结
用户碰触移动页面之后,需要等待一段时间来判断是不是双击(double tap)动作(双击放大),而不是立即响应单击click,等待的这段时间大约是300ms,因此移动端click有300ms延迟,较好解决方法是使用touchend替换click事件,但注意在手势检测中屏蔽掉对以上模拟的影响。
知识点补充:
- pointer-events:none;由CSS3提出,不只是禁用链接hover,打开链接等效果,是真实意义上的将onlick事件去掉了,注意该样式只禁用了鼠标事件,对应的键盘事件并没有被禁用(tab选中,Enter提交等)。
PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedown、mouseup、mousemove和click事件。一次点击行为,可被拆解成:mousedown -> mouseup -> click 三步。
手机上没有鼠标,所以就用触摸事件去实现类似的功能。touch事件包含touchstart、touchmove、touchend,注意手机上并没有tap事件。手指触发触摸事件的过程为:touchstart -> touchmove -> touchend ->300ms->click。