移动端点击为什么有300ms延迟?怎么解决?

薪羽🍀 阅读 16

我在用 Vue 做一个移动端的按钮,点下去总感觉卡一下才触发,查了下说是 300ms 延迟的问题。试过加 touch-action: manipulation,但好像没用,求问怎么彻底解决?

这是我的代码:

<template>
  <button @click="handleClick">点我</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('clicked!');
    }
  }
}
</script>
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
小紫晨
小紫晨 Lv1
300ms 延迟是早期移动端 Safari 为识别双击缩放而设计的机制,后来其他浏览器也跟进。不过现在主流移动浏览器(iOS Safari 13+、Android Chrome 56+)已经默认禁用了这个延迟,前提是你的页面设置了正确的 viewport。

你先确认下 里有没有这一行:

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


注意 user-scalable=no 这个很关键——如果没加,或者写了 user-scalable=yes,某些老设备上还会触发 300ms 延迟。

如果加了还是卡,大概率是旧设备或某些 WebView 容器(比如老版微信内置浏览器)的问题。这时候性能上最干净的方案是用 touchstart 替代 click,因为 touchstart 是毫秒级触发的,没有延迟:

<template>
<button @touchstart="handleClick" @click.prevent>点我</button>
</template>

<script>
export default {
methods: {
handleClick(e) {
// 防止长按弹出菜单等副作用
e.preventDefault()
console.log('clicked!')
}
}
}


或者用 touchend + 手动判断是否是有效点击(防止滑动误触):

<template>
<button ref="btn" @touchstart="onTouchStart" @touchend="onTouchEnd" @click="handleClick">点我</button>
</template>

<script>
export default {
data() {
return {
touchStartPos: null
}
},
methods: {
onTouchStart(e) {
this.touchStartPos = { x: e.touches[0].clientX, y: e.touches[0].clientY }
},
onTouchEnd(e) {
const endPos = { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY }
if (Math.abs(endPos.x - this.touchStartPos.x) > 10 || Math.abs(endPos.y - this.touchStartPos.y) > 10) {
this.touchStartPos = null
return
}
this.handleClick(e)
},
handleClick(e) {
console.log('clicked!')
}
}
}


不过更推荐用 fastclick 库(虽然有点老但稳定),或者直接升级项目依赖,Vue 3 + Vite 默认生成的 index.html 里已经自动加了合适的 viewport,基本不会踩坑。

最后提醒:touch-action: manipulation 只是告诉浏览器「别等双击缩放了」,但某些老 WebView 里它根本不认,所以别光指望它。
点赞 6
2026-02-25 20:14