在移动设备上,浏览器为了区分单击(tap)和双击缩放(double tap to zoom),会给 click 事件添加约 300ms 的延迟。在用户点击屏幕后,浏览器会等待约 300ms,如果没有第二次点击,才会触发 click 事件。
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
这种方式最简单,但会完全禁用用户缩放功能。
2. 使用 CSS 的 touch-action 属性html {
touch-action: manipulation; /* 禁用双击缩放 */
}
或更细粒度控制:
button {
touch-action: manipulation; /* 只对按钮禁用 */
}
manipulation 值会禁用双击缩放,但保留滚动手势。
// 安装:npm install fastclick
import FastClick from 'fastclick';
// 初始化
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
4. 现代浏览器自动优化
现代浏览器在以下情况下会自动移除 300ms 延迟:
<meta name="viewport" content="width=device-width">user-scalable=no)touch-action: manipulation 样式element.addEventListener('pointerup', function(event) {
// 立即触发,无延迟
});
6. 使用触摸事件(Touch Events)模拟
let tapDelayTimer;
let touchStartTime;
element.addEventListener('touchstart', function(event) {
touchStartTime = Date.now();
});
element.addEventListener('touchend', function(event) {
// 计算触摸时长
let touchDuration = Date.now() - touchStartTime;
// 如果触摸时间短(例如小于 500ms),认为是点击
if (touchDuration < 500) {
event.preventDefault();
// 触发自定义的点击事件
triggerCustomClick(event);
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* 禁用双击缩放,保留其他触摸交互 */
* {
touch-action: manipulation;
}
</style>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
方案二:框架内置解决方案
React(React 18+ 已自动处理)
// React 默认优化了移动端点击延迟
<button onClick={handleClick}>点击我</button>
Vue(使用 vue-touch 或手动处理)
// 使用 vue-touch 插件
import VueTouch from 'vue-touch'
Vue.use(VueTouch, { name: 'v-touch' })
// 检测设备是否还有 300ms 延迟
function hasClickDelay() {
const startTime = Date.now();
const testDiv = document.createElement('div');
testDiv.addEventListener('click', function() {
const delay = Date.now() - startTime;
console.log(`点击延迟:${delay}ms`);
});
document.body.appendChild(testDiv);
// 模拟点击
const touchEvent = new TouchEvent('touchend', {
bubbles: true,
cancelable: true
});
testDiv.dispatchEvent(touchEvent);
testDiv.click();
document.body.removeChild(testDiv);
}
touch-action: manipulation 需要较新的浏览器版本touchstart 或 touchend 中执行耗时操作
<meta name="viewport" content="width=device-width, initial-scale=1">touch-action: manipulation 或 touch-action: pan-y pinch-zoom通过以上方法,可以显著提升移动端的点击响应速度,改善用户体验。