背景
在移动端开发中,事件触发的顺序依次是
- touchstart
- touchmove
- touchend
- click
从touchend到click之间存在300ms延迟,原因是浏览器为了区分点击事件和双击事件,让click延迟300ms再进行响应,如果300ms内点击两次则响应双击事件,否则响应单击事件。
click的300ms延迟可能会产生点击穿透的问题。
例如,页面有两个元素A和B,B位于A元素的上层,B监听touch事件,当touch时隐层B元素(常见于蒙层弹窗),300ms后click事件会作用于相同坐标位置的元素,由于B元素被隐藏,那么会作用于下层的A,触发A的click事件,就好像click事件从上层穿透到下层一样。
解决方案
- 只使用touch事件,不使用click事件
需要注意a标签默认的href跳转是通过click响应的 - 只使用click事件,不使用touch事件
会影响用户交互,每次点击都有延迟 - 取消双击缩放事件,这样不会有300ms延迟
html {
touch-action: manipulation; // IE11+,只允许滚动和持续缩放,其他默认支持的行为都会被禁用;例如双击缩放
-ms-touch-action: manipulation; // IE10
}
- 设置页面不允许缩放,间接取消了双击事件和300ms延迟
<meta name="viewport" content="user-scalable=no" />
- 使用fastclick三方库
fastclick库的原理:在 touchend 阶段 调用 event.preventDefault阻止原生的事件冒泡,然后通过 document.createEvent 手动创建一个 MouseEvents,然后 通过 eventTarget.dispatchEvent 触发对应目标元素上绑定的 click 事件。简而言之,劫持了原生事件,然后自己触发click事件