我在做移动端弹窗时,点击关闭按钮后,下面的元素也被触发了,这应该是点击穿透吧?
试过用 preventDefault() 和 stopPropagation(),但好像没用。弹窗是用 fixed 定位盖在页面上的,点击关闭后立即移除 DOM,结果底下的按钮就被点到了。
closeBtn.addEventListener('touchend', function(e) {
e.preventDefault();
e.stopPropagation();
modal.remove(); // 移除弹窗
});
首先你要明白点击穿透的原理。移动端点击事件有300ms延迟,当你快速点击关闭按钮时,touchend事件触发了,弹窗被移除,但300ms后浏览器还会触发click事件,这时弹窗已经不存在了,click事件就穿透到下层元素了。
解决方法有好几种,我来推荐最稳妥的:
方案一:给关闭按钮加延迟移除弹窗
方案二:直接在body上阻止默认行为(更彻底)
方案三:用fastclick库(长期项目推荐)
这个库会消除300ms延迟,从根本上解决问题:
为什么preventDefault和stopPropagation没用?因为它们只能阻止当前事件,但阻止不了浏览器自动触发的后续click事件。所以要么延迟处理,要么从根本上消除延迟。
个人建议如果是小项目用方案一就行,长期维护的项目用方案三。我通常都用fastclick,一劳永逸。