移动端点击的300ms延迟

有300ms延迟的原因

  之所以移动端click会有300ms的延迟,主要是为了让用户在双击屏幕时可以对视图进行放大缩小,而这300ms就是用于判断在这时间范围之内是否有第二次点击,有则双击,否则就是单击。若每次单击屏幕都会延迟300ms才触发事件,很明显这对于用户体验来说是极其不友好的。

解决300ms延迟的办法

zepto.js

  在zepto.js这个JavaScript库里,使用touch事件封装了tap事件,模仿了click的实现,并且不会有300ms的延迟。实现思路是:给目标元素添加touch监听事件,只要满足touch的时间不超过规定的超时时间(防止长按),并且touch过程不发生移动则在touchend时触发tap事件。(touchend事件是冒泡到document时才触发目标元素绑定的tap事件的)

zepto.js的穿透bug

  zepto.js虽然使用tap事件模拟click避开了300ms延迟,但存在一个bug,即点击穿透。这里需要先说明的是,当用户手指触摸到屏幕的时候,系统会生成两个事件,一个是touch,另一个是click,执行顺序依次为:touchstart、touchmove、touchend、click。其中touch事件会优先处理,经过捕获、处理,、冒泡一系列流程完成后才回去触发click事件。

  所谓的点击穿透,是指当用户在上层有一个模态框或覆盖层(诸如蒙版)时,当触发tap事件关闭掉模态框或覆盖层后,此时事件只进行到touchend阶段,而300ms后将会触发的click事件在上层失去了目标元素,若此时下层的位置上恰好有元素绑定了click事件或是click时会触发事件,诸如input输入框在focus时会弹出键盘,a标签会跳转链接等的元素时,则会触发其绑定的click事件。

解决穿透的办法

  1:在touch事件里面,调用e.preventDefault()可以阻止本次点击触发的click事件,而且不会阻止后续的touch事件。
  2: 对tap事件做一下延迟,加一个setTimeout来使上层的模态框或覆盖层等click事件触发后再消失,这样下层的元素就不会被暴露出来了,click事件自然也不会作用到下层元素上去。
  3:使用css的pointer-events给下层那个会触发到click的元素添加pointer-events:none属性,这会使得该元素永远不会成为click事件的目标。需要的话可以再添加一个setTimeout再把 pointer-event 的值设回auto。

fastclick

实现原理:

  监听touchstart事件获取目标元素。监听到touchend事件后,使用e.preventDefault()取消掉300ms后的click,合成相应的click事件并立即触发达到fastclick的目的。(合成事件的三步骤:创建事件初始化鼠标事件给目标元素分发事件)

不需要使用fastclick的场景

(上述图片来源于网络)


 上一篇
CSS常见的几种布局方式 CSS常见的几种布局方式
未知宽高元素的水平垂直居中<div class="container"> <div class="ele">hello world</div> </div> /* 为了便于观察,先设置一些css样式: */
2019-03-07
下一篇 
0.1 + 0.2 !== 0.3 0.1 + 0.2 !== 0.3
  众所周知的是,计算机中对十进制数字的运算是先把十进制数字转换为二进制再进行运算的(至于为什么,呃,如果我没记错的话,大致是因为早期计算机只支持二进制?正如之前看到的一句话,二进制是世界的本源)。对于二进制浮点数的转
2019-03-02
  目录