click事件延迟300ms以及点击穿透的原因及解决

 移动端click事件延迟300ms的原因

这要追溯至 2007 年初。苹果公司在发布首款 iPhone 前夕,遇到一个问题—— 当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone这种小屏幕浏览桌面端站点的问题。这当中最出名的,当属双击缩放(double tap to zoom)。这也是会有上述 300 毫秒延迟的主要原因。当用户一次点击屏幕之后,浏览器并不能立刻判断用户是要进行双击缩放,还是想要进行单击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。

以及解决办法

禁用缩放:简单,但同时也使的网页无法缩放,不适用于未对移动端浏览做适配优化的网页。
更改默认视口宽度:简单,但需要浏览器支持。
指针事件和css touch-action:新属性,可能存在浏览器兼容问题,如仅为解决点击延迟问题儿引入一整套指针事件有点过了。
tap事件:能较好解决点击延迟,并且对其他移动端触摸事件也有较好支持,但存在点透问题,不知最新版是否解决。
fastclick:当前较好的专门解决点击延迟的库,脚本尺寸相对较大。
基本原理:FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉。

点击穿透发生的条件

A 和 B不是后代继承关系(如果是后代继承关系的话,就直接是冒泡子类的话题了)

A发生touch, A touch后立即消失, B事件绑定click

A z-index大于B,即A显示在B浮层之上

解析:

事件执行顺序,touchstart -> touchmove -> touchend -> click
当手指触摸到屏幕的时候,系统生成两个事件,一个是touch 一个是click,touch先执行,touch执行完成后,A从文档树上面消失了,而且由于移动端click还有延迟200-300ms的关系,当系统要触发click的时候,发现在用户点击的位置上面,目前离用户最近的元素是B,所以就直接把click事件作用在B元素上面了.
解决方法:

只用touch或只用click,注意a标签的href也是click,需要去掉换成js控制的跳转

fastclick:在没有标记使用click的元素上,阻止click事件的派发,即阻止事件冒泡。将click事件在外层父盒子就隔断。

在项目中,某些用touchend事件作为click事件补充的兄弟,点击穿透的事情你遇见了吗?如果用到touch事件,在一些效果实现上面,使用touchstart事件会比touchend事件给人的感觉灵敏!

原文地址:https://www.cnblogs.com/ns10086/p/9304863.html