移动端点击穿透问题,300ms延时问题

164 阅读2分钟

背景

在移动端开发中,事件触发的顺序依次是

  1. touchstart
  2. touchmove
  3. touchend
  4. click

从touchend到click之间存在300ms延迟,原因是浏览器为了区分点击事件和双击事件,让click延迟300ms再进行响应,如果300ms内点击两次则响应双击事件,否则响应单击事件。

click的300ms延迟可能会产生点击穿透的问题。
例如,页面有两个元素A和B,B位于A元素的上层,B监听touch事件,当touch时隐层B元素(常见于蒙层弹窗),300ms后click事件会作用于相同坐标位置的元素,由于B元素被隐藏,那么会作用于下层的A,触发A的click事件,就好像click事件从上层穿透到下层一样。

解决方案

  1. 只使用touch事件,不使用click事件
    需要注意a标签默认的href跳转是通过click响应的
  2. 只使用click事件,不使用touch事件
    会影响用户交互,每次点击都有延迟
  3. 取消双击缩放事件,这样不会有300ms延迟
html { 
    touch-action: manipulation; // IE11+,只允许滚动和持续缩放,其他默认支持的行为都会被禁用;例如双击缩放 
    -ms-touch-action: manipulation; // IE10 
}
  1. 设置页面不允许缩放,间接取消了双击事件和300ms延迟
<meta name="viewport" content="user-scalable=no" />
  1. 使用fastclick三方库
    fastclick库的原理:在 touchend 阶段 调用 event.preventDefault阻止原生的事件冒泡,然后通过 document.createEvent 手动创建一个 MouseEvents,然后 通过 event​Target​.dispatch​Event 触发对应目标元素上绑定的 click 事件。简而言之,劫持了原生事件,然后自己触发click事件