移动页面事件穿透/点击穿透问题

一、背景

博主所负责其中一个项目是web页面,在移动端上出现了事件穿透问题,开发介绍问题原因后,发觉是移动web一个知识点,值得记录一下。

二、click与300ms延迟

移动浏览器提供一个特殊的功能:双击(double tap)放大

300ms的延迟就来自这里,用户触碰页面之后,需要等待一段时间来判断是不是双击(double tap)动作,而不是立即响应click(单击),等待的这段时间大约是300ms。

  1. 移动端touch事件提供:touchstarttouchmovetouchend,却没有tap支持;
  2. 主流框架/库都是手动实现了tap事件,以求消除300ms延迟,提高页面响应速度
  3. 对于简单的页面,可以把 touchstart 或者 touchend 当作tap来用,但存在一些问题,比如手指接触目标元素,按住不放,慢慢移出响应区域,会触发 touchstart 事件执行对应的事件处理器(本不应该触发),touchend 事件也存在类似的问题。
  4. 使用原生的touch事件存在点击穿透的问题,因为click是在touch系列事件发生后大约300ms才触发,混用touchclick肯定会导致事件穿透。
  5. 手机上响应click事件有300ms的延迟,会有响应慢/延迟的感觉,因此很多移动页面会使用touch/tap事件。

三、tap事件

用过Zepto或者KISSY等移动端js库的人肯定对tap事件不陌生,我们做PC页面时候绑定click,相应地手机页面就绑定tap。但原生的touch事件本身是没有tap的,js库提供的tap事件都是模拟出来的。

Zepto中对tap事件处理:如果在touched响应250ms无操作后,则触发singleTap。即事件触发顺序为:touch-tap-click。

三、点击穿透问题

点击穿透现象有3种:

  • 点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件。
    • 解析:蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件。touch事件触发之后,蒙层消失了,300ms后这个点击的click事件fire,event的target自然就是按钮下面的元素。
  • 跨页面点击穿透问题:如果按钮下面恰好是有href属性的a标签,那么页面就会发生调整。因为a标签跳转默认是click事件触发。原因同上。
  • 第三种:这次没有mask,直接点击页面内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了。
    • 解析:和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况。

四、解决方案

思路:

  1. 不要混用touch和click:touch之后300ms会触发click,只有touch或者只用click就自然不会存在问题。

  2. 吃掉/消费掉touch之后的click

    依旧使用tap,只是在可能发生点击穿透的情形下做额外的处理,拿个东西来挡住、或者tap后延迟350ms再隐藏mask、pointer-events、在下面元素的事件处理器里做检测。

我们对事件响应速度要求不高,最后是通过延迟隐藏/关闭mask/弹窗解决的,简单可控哈。

参考:https://juejin.im/entry/56ce9c97c24aa80052101aab

你可能感兴趣的:(移动页面事件穿透/点击穿透问题)