出处:掘金

原作者:江城开朗的豌豆


为什么会有 300ms 延迟?

在移动端,为了让用户能双击缩放(Double Tap to Zoom),浏览器在点击事件上设置了一个 300ms 的等待期,用户点了之后,浏览器会先等 300ms,确认没有第二次点击后,才触发事件

问题:按钮点击反应慢

如何干掉这 300ms 延迟?

1. 使用 touchstart 替代 click(慎用!)

button.addEventListener('touchstart', () => {
  console.log('这次反应够快了吧!');
});
  • 优点:瞬间触发,没有延迟
  • 缺点:touchstart 会在手指刚触碰屏幕时就触发,可能导致误触(比如用户只是想滑动,却误点了按钮)

2. 设置 <meta> 标签,禁止缩放

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

这样浏览器就知道这个页面不需要双击缩放,自然就不会有 300ms 延迟了

  • 适用场景:纯交互型 H5 页面,不需要缩放功能

3. 使用 FastClick 库(经典方案)

// 安装:npm install fastclick
import FastClick from 'fastclick';
FastClick.attach(document.body);
  • 原理:用 touch 事件模拟 click,并立即触发,绕过浏览器的等待机制
  • 适用场景:需要兼容老项目,或者不想手动处理 touch 事件的情况

4. 直接使用 CSS 的 touch-action(现代浏览器推荐)

button {
  touch-action: manipulation; /* 告诉浏览器:这个元素只允许滚动和连续触摸,不需要双击缩放 */
}
  • 优点:纯 CSS 方案,无需 JS,性能更好
  • 兼容性:现代浏览器基本都支持,IE 不行

为什么现在很多项目不用管 300ms 问题了?

随着移动端生态的成熟,现代浏览器(Chrome、Safari等)在 2015 年后逐步优化了这一机制:

  • 如果页面设置了 <meta viewport>width=device-width,大部分浏览器会自动禁用 300ms 延迟
  • 新版 Chrome 和 Firefox 在移动端已经默认去除了延迟

但如果你的用户还在用老版本浏览器(比如某些国产安卓机的内置浏览器),可能还是会有这个问题

总结:如何优雅处理点击延迟?

  1. 优先使用 <meta viewport> + touch-action: manipulation(最简单、性能最好)
  2. 如果需要兼容老旧设备,可以用 FastClick
  3. 除非特殊需求,别用 touchstart 替代 click,容易引发误触问题