Zepto tap 的"点透"问题

1. 什么是"点透"?

在列表页面上创建一个弹出层,弹出层有个关闭按钮。点击这个按钮关闭弹出层后,按钮正下方的内容也会执行点击事件(或打开链接)。这种现象被定义为"点透"。

2. 点透原因

  • Zepto 的 tap 通过监听绑定在 document 上的 touch 事件模拟。
  • tap 事件是冒泡到 document 上触发的。
  • 在 tap 完成时(touchstart / touchend),需要冒泡到 document 才触发;而冒泡到 document 之前,touchstart / touchend 会先触发 click。
  • 因为 click 有大约 300ms 延迟(为实现 Safari 的双击事件),而 tap 立即触发,所以看起来就像"穿透"。

3. 解决方案

方案一:使用 FastClick

window.addEventListener('load', function () {
  FastClick.attach(document.body);
}, false);

// 或者 require
var FastClick = require('fastclick');
FastClick.attach(document.body, options);

方案二:用 touchend 代替 tap,并 preventDefault()

$('#cbFinish').on('touchend', function (event) {
  // 很多处理比如隐藏什么的
  event.preventDefault();
});

方案三:延迟一定时间(300ms+)处理事件

$('#cbFinish').on('tap', function (event) {
  setTimeout(function () {
    // 很多处理比如隐藏什么的
  }, 320);
});

这种方法可以和 fadeIn / fadeOut 等动画结合使用,做出过渡效果。

4. 现代方案

现代移动端一般直接用 click 事件 + 阻止冒泡,或在 Vue/React 等框架中用官方推荐的 @click 即可避免此问题(框架的事件系统通常已经处理过)。如果必须用 tap,搭配 pointer-events / touch-action 也是可行的兜底策略。

来源整理自:我的有道云笔记