做有态度的前端团队

网易FEG前端团队

移动端300ms点击延迟和点击穿透问题

闲暇中get到一点小知识,整理一下与大伙分享。

一、移动端300ms点击延迟

一般情况下,如果没有经过特殊处理,移动端浏览器在派发点击事件的时候,通常会出现300ms左右的延迟。也就是说,当我们点击页面的时候移动端浏览器并不是立即作出反应,而是会等上一小会儿才会出现点击的效果。

原因

早些时候为了应对小屏幕浏览桌面端站点的问题,于是有了双击缩放,也是上述300 毫秒延迟的主要原因。
双击缩放与300ms延迟的联系:
假定这么一个场景。用户在移动端浏览器点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,浏览器就等待了300ms,以判断用户是否再次点击了屏幕。

浏览器开发商的解决方案:

方案一:禁用缩放

<meta name="viewport" content="user-scalable=no"/>
<meta name="viewport" content="initial-scale=1,maximum-scale=1"/>

浏览器禁止默认的双击缩放也就去掉了300ms的点击延迟。

缺点:我们的初衷并不是要完全禁止双击缩放,我们还是希望能够通过双击缩放来放大图片或文字。

方案二:更改默认的视口宽度

一开始,为了让桌面站点能在移动端浏览器正常显示,移动端浏览器默认的视口宽度并不等于设备浏览器视窗宽度,而是要比设备浏览器视窗宽度大,通常是980px。我们可以通过以下标签来设置视口宽度为设备宽度。

<meta name="viewport" content="width=device-width"/>

随着响应式设计的普及,浏览器能够识别出一个网站是响应式的网站,那么移动端浏览器就可以自动禁掉默认的双击缩放行为并且去掉300ms的点击延迟。所以加了上述标签的浏览器认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了。

方案三:CSS touch-action

这个属性指定了相应元素上能够触发浏览器的默认行为。

touch-action: none;

设置该属性为none便不会触发浏览器的任何默认行为,就无需进行300ms的延迟判断。

但是,到目前为止,以上三种方案并不能提供很好的兼容性。有待验证!!!

现有的解决方案

方案一:FastClick

FastClick 是 FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉。

二、点击穿透问题

既然click点击有300ms的延迟,那对于触摸屏,我们直接监听touchstart事件不就好了吗?
使用touchstart去代替click事件有两个不好的地方。
第一:touchstart是手指触摸屏幕就触发,有时候用户只是想滑动屏幕,却触发了touchstart事件,这不是我们想要的结果;
第二:使用touchstart事件在某些场景下可能会出现点击穿透的现象。

什么是点击穿透?

假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。

手机阅读请扫描下方二维码:

none