移动端触摸事件阻止冒泡后父元素点击还是触发了怎么办?

雨欣酱~ 阅读 39

我在开发移动端列表滑动删除功能时遇到问题。子元素的touchstart事件里用了e.stopPropagation(),但父元素的点击事件还是会被触发,这是为什么呢?

具体场景是这样的:列表项有一个可滑动的删除按钮(子元素),外面包裹着点击跳转的父元素。当手指在子元素滑动时,既要阻止父元素跳转,又不能影响正常点击列表项。但现在的效果是,即使在子元素滑动,松手后父元素的点击事件还是会触发。

尝试过在子元素的touchstart里写:


function handleTouchStart(e) {
  e.stopPropagation(); // 已经阻止冒泡了呀
  // 处理滑动逻辑...
}

但父元素的click事件监听还是会被触发。难道是移动端事件机制和PC端不同?有没有更好的方式同时阻止冒泡和默认行为?

我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
Mc.伊可
Mc.伊可 Lv1
这个问题确实有点棘手,但其实是因为移动端的事件机制和PC端不太一样。在移动端,touch事件和click事件是分开的,即使你在touchstart里阻止了冒泡,click事件还是可能会被触发。

可以试试这样,在子元素的touchstart事件里,除了调用e.stopPropagation(),还需要加上e.preventDefault()来阻止默认行为。另外,为了彻底避免父元素的点击事件被触发,可以在touchstart的时候给父元素加一个标志位,用来判断是否需要执行点击逻辑。

下面是一个完整的解决方案:


let isTouchMove = false; // 标志位,判断是否有滑动操作

function handleTouchStart(e) {
e.stopPropagation();
e.preventDefault(); // 阻止默认行为
isTouchMove = false; // 初始化标志位
}

function handleTouchMove(e) {
e.stopPropagation();
e.preventDefault(); // 阻止默认行为
isTouchMove = true; // 标记为滑动状态
}

function handleTouchEnd(e) {
if (isTouchMove) {
e.stopPropagation();
e.preventDefault(); // 如果有滑动,阻止后续的click触发
}
}

function handleClick(e) {
if (isTouchMove) {
e.stopPropagation();
return; // 如果之前有滑动,直接返回不执行点击逻辑
}
// 正常处理点击跳转逻辑
console.log('父元素点击事件触发');
}

// 绑定事件
const childElement = document.querySelector('.child');
const parentElement = document.querySelector('.parent');

childElement.addEventListener('touchstart', handleTouchStart);
childElement.addEventListener('touchmove', handleTouchMove);
childElement.addEventListener('touchend', handleTouchEnd);

parentElement.addEventListener('click', handleClick);


这里的关键点是通过标志位isTouchMove来区分用户是在滑动还是点击。如果检测到滑动操作,就阻止父元素的点击逻辑;如果没有滑动,则正常执行点击跳转。

顺便吐槽一句,移动端事件这块儿真是让人头大,我也踩过类似的坑,希望这个方法能帮你解决问题!
点赞 1
2026-02-16 10:01
慕容树泽
在移动端,光靠 e.stopPropagation() 是不够的,因为 click 事件是独立触发的,它并不完全依赖冒泡机制。你得在 touchstarttouchmove 里调用 e.preventDefault() 来阻止默认行为。

我之前这样搞的,给子元素加个标志位判断是否滑动过:

let isMoved = false;

function handleTouchStart(e) {
isMoved = false;
}

function handleTouchMove(e) {
isMoved = true;
e.stopPropagation();
e.preventDefault(); // 阻止默认行为
}

function handleTouchEnd(e) {
if (isMoved) {
e.stopPropagation();
e.preventDefault(); // 如果滑动过,阻止点击
}
}

// 父元素的点击事件
function handleClick(e) {
console.log('父元素点击');
}


记得把 touchstarttouchmovetouchend 都绑上,这样就能区分滑动和点击了。别问我为什么知道,被坑过好多次才搞定的。
点赞 4
2026-02-14 04:02