为什么触摸事件在事件委托时target总是父元素?
在移动端用事件委托处理多个.item元素的touchstart事件,但发现e.target始终返回父元素div.box,而不是实际点击的子元素。我尝试过把事件绑定到父元素并用closest()方法筛选,但子元素上的点击完全没反应。
代码结构是这样的:
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
</div>
JS部分用了:
document.querySelector('.box').addEventListener('touchstart', function(e) {
const target = e.target.closest('.item');
if (target) console.log('clicked:', target.textContent);
});
但点击子元素时控制台没有任何输出,直接点击父容器才会触发。是不是触摸事件的事件冒泡机制和鼠标事件不一样?
但更可能的问题是——你实际点击的区域根本没被 .item 占满。比如你给 .item 加了 padding 或 margin,但没设置
box-sizing: border-box,或者 .item 的高度为 0(比如内容是空的、没高度),那 touchstart 的e.target就会落在父级 .box 上,而不是子元素上。先确认下你的 CSS 有没有类似问题:
如果 CSS 没问题,再加个兜底逻辑:别光用
closest('.item'),先打印e.target看看到底是谁:如果你发现
e.target是 .box,但点击的是 .item 里的文字,那大概率是 .item 元素本身被其他层遮挡了(比如伪元素覆盖、absolute 定位的透明层),或者用了pointer-events: none。还有一种情况是:你用的是旧版 iOS Safari(比如 iOS 12 以前),它在 touchstart 里
closest行为不稳定,可以改用matches('.item')+parentElement一层层往上找:不过现在主流基本没问题,优先检查下 DOM 结构和 CSS 渲染尺寸吧,我遇到十次有九次是 item 高度为 0 或被遮挡。
试试直接用 e.target 判断,而不是 closest(),像这样:
如果还是不行,检查一下 CSS,确保 .item 元素不是被意外的层级遮挡了,或者尝试给 .box 和 .item 加上 pointer-events: auto; 看看有没有效果。