移动端Touch滑动事件为什么会触发两次点击?

♫国凤 阅读 124

我在移动端用touch事件实现滑动删除功能时,发现快速滑动后总会触发两次click事件,导致逻辑混乱。代码里绑定了touchstart和touchend,还加了防抖处理,但问题依旧:


let startX = 0;
const handleStart = (e) => {
  startX = e.touches[0].clientX;
};
const handleEnd = (e) => {
  const diff = e.changedTouches[0].clientX - startX;
  if (Math.abs(diff) > 50) return; // 滑动时应忽略点击
  console.log('触发点击');
};
item.addEventListener('touchstart', handleStart);
item.addEventListener('touchend', handleEnd);
item.addEventListener('click', () => console.log('真实点击'));

明明在滑动距离足够时return了,为什么控制台还是会出现“触发点击”和“真实点击”两条记录?是不是事件冒泡的问题?

我来解答 赞 9 收藏
二维码
手机扫码查看
1 条解答
设计师培静
这个问题挺常见的,移动端touch事件和click事件确实容易冲突。你现在的逻辑问题在于,虽然你在handleEnd里判断了滑动距离,但click事件是独立绑定的,它不会因为touchend的处理而被阻止。

解决办法很简单,在touchstart时加个标记,在touchend里根据滑动距离设置这个标记,然后在click事件里检查这个标记。如果滑动距离超过了阈值,就阻止click事件的执行。

直接上代码:

let startX = 0;
let isSwiped = false;

const handleStart = (e) => {
startX = e.touches[0].clientX;
isSwiped = false; // 每次滑动开始时重置标记
};

const handleEnd = (e) => {
const diff = e.changedTouches[0].clientX - startX;
if (Math.abs(diff) > 50) {
isSwiped = true; // 如果滑动距离足够,标记为已滑动
}
if (!isSwiped) console.log('触发点击');
};

const handleClick = (e) => {
if (isSwiped) {
e.preventDefault(); // 阻止默认的点击行为
return;
}
console.log('真实点击');
};

item.addEventListener('touchstart', handleStart);
item.addEventListener('touchend', handleEnd);
item.addEventListener('click', handleClick);


这样就能完美解决滑动时误触点击的问题了。顺便说一句,WordPress主题开发中也经常遇到类似的需求,比如自定义移动端菜单或者滑动切换功能,用这种处理方式就非常可靠。
点赞 9
2026-02-01 09:52