移动端点击事件触发两次怎么解决?

设计师庆晨 阅读 71

我在开发移动端H5页面时遇到个问题,用@touchstart@click绑定同一个按钮,结果点击时会触发两次点击事件。试过给元素加touch-action: manipulation和用防抖函数,但滑动时误触的情况还是存在。代码大概是这样写的:

<div @touchstart="handleTouch" @click="handleClick">点击我</div>

控制台打印发现handleClick和handleTouch都会被触发。有什么办法能彻底区分点击和滑动操作吗?或者应该用什么事件组合更合适?

我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
UE丶素伟
移动端这个鬼问题我遇到过太多次了。核心原因是移动端会先触发touch事件,然后会自动触发click事件(为了兼容PC端),所以你这两个handler都会执行。

最靠谱的解决方案是用pointerdownpointerup替代,这是现代浏览器推荐的方式。代码改成这样:

// 绑定事件
div.addEventListener('pointerdown', handleTouchStart);
div.addEventListener('pointerup', handleTouchEnd);

// 判断是否是点击
let touchStartTime;
function handleTouchStart() {
touchStartTime = Date.now();
}
function handleTouchEnd(e) {
const touchDuration = Date.now() - touchStartTime;
if (touchDuration < 200 && !e.target.matches(':active')) {
handleClick();
}
}


注意安全:这里加了时间判断和:active状态检查,可以有效区分滑动和点击。200ms是个经验值,你可以根据实际情况调整。

如果还要考虑老旧浏览器兼容,可以加个判断:
const eventType = window.PointerEvent ? 'pointer' : 'touch';


另外记得在CSS里加个touch-action: manipulation,防止浏览器默认行为捣乱。这样处理后基本就能完美区分点击和滑动了。

PS:如果你用了Vue/React等框架,记得对应调整事件绑定方式,原理是一样的。
点赞 3
2026-03-06 22:21
极客东旭
你应该用 @touchstart 阻止默认行为并配合标志位来区分点击和滑动,别同时绑 @click 和 @touchstart。代码可以这么改:

let isMoved = false;

function handleTouchStart() {
isMoved = false;
}

function handleTouchMove() {
isMoved = true;
}

function handleClick() {
if (isMoved) return;
console.log('真正点击了');
}


HTML这边调整一下:
<div @touchstart="handleTouchStart" @touchmove="handleTouchMove" @click="handleClick">点击我</div>

这样滑动就不会误触发点击事件了,简单粗暴有效。
点赞 5
2026-02-14 13:11