Press手势在移动端怎么才能准确触发?
我在用 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>
iOS 的 touchend 事件在某些场景下会被系统拦截,比如用户快速点击或者页面有滚动的时候。而且单纯靠 touchstart/touchend 判断的话,用户手指稍微滑动一下也会触发长按,这体验肯定不行。
核心要做的就三件事:阻止默认行为防止系统干扰、判断用户是否在滑动、确保在各种情况下都能清理掉计时器。
改一下你的代码:
然后模板里补上 touchmove:
@touchstart="onTouchStart"
@touchend="onTouchEnd"
@touchcancel="onTouchCancel"
@touchmove="onTouchMove"
>长按我
几点说明:
iOS 上建议在 touchstart 里调用 preventDefault,但这样会阻止元素的可点击行为。如果你的按钮在列表里需要滚动,可能得用 CSS 的 touch-action: manipulation 或者更复杂的逻辑来区分「滚动」和「长按」。
如果你的项目依赖比较成熟的手势库,hammerjs 或者 vueuse 的 useLongPress 都已经处理了这些兼容问题,能省很多心。