Press手势在移动端怎么才能准确触发?

欧阳乙豪 阅读 12

我在用 Vue 开发一个移动端的按钮组件,想实现长按(Press)效果,但发现有时候点一下就触发了,有时候又完全没反应。我试过用 touchstart 和 touchend 计算时间差,但体验很不稳定,尤其在 iOS 上。

下面是我目前的写法,逻辑是按下超过 500ms 才触发 press 事件,但实际测试时经常误判,是不是哪里漏了什么?比如要不要阻止默认行为或者处理 touchmove?

<template>
  <div
    @touchstart="onTouchStart"
    @touchend="onTouchEnd"
    @touchcancel="onTouchEnd"
  >长按我</div>
</template>

<script>
export default {
  methods: {
    onTouchStart() {
      this.timer = setTimeout(() => this.$emit('press'), 500);
    },
    onTouchEnd() {
      clearTimeout(this.timer);
    }
  }
}
</script>
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
萌新.松奇
你的问题在于 iOS 上 touchend 有时候不会触发,而且没有处理用户误触滑动的情况。

iOS 的 touchend 事件在某些场景下会被系统拦截,比如用户快速点击或者页面有滚动的时候。而且单纯靠 touchstart/touchend 判断的话,用户手指稍微滑动一下也会触发长按,这体验肯定不行。

核心要做的就三件事:阻止默认行为防止系统干扰、判断用户是否在滑动、确保在各种情况下都能清理掉计时器。

改一下你的代码:



然后模板里补上 touchmove:



几点说明:

iOS 上建议在 touchstart 里调用 preventDefault,但这样会阻止元素的可点击行为。如果你的按钮在列表里需要滚动,可能得用 CSS 的 touch-action: manipulation 或者更复杂的逻辑来区分「滚动」和「长按」。

如果你的项目依赖比较成熟的手势库,hammerjs 或者 vueuse 的 useLongPress 都已经处理了这些兼容问题,能省很多心。
点赞
2026-03-11 18:06