@tap.stop 是 uni-app 中阻止事件冒泡的推荐写法,配合 pointer-events: none 和足够 z-index 的遮罩层,可彻底解决点击/滑动穿透问题。

用 @tap.stop 是最直接的阻止冒泡方式
在 uni-app 里,@tap 是比 @click 更可靠的手势事件绑定方式,而加上 .stop 修饰符后,它会在触发回调前立刻调用 event.stopPropagation(),无需手动写逻辑。这不是“可选优化”,而是推荐默认写法。
- 不加
.stop:遮罩层点击后,事件仍会冒泡到下层view或uni-list-item,iOS 尤其明显 - 加了
.stop:哪怕遮罩层是半透明、z-index略低,也能从源头掐断穿透路径 - 注意:小程序端可用
catchtap替代(效果等价),但 H5 和 App 端不支持,跨平台项目统一用@tap.stop更稳妥
pointer-events: none 动态禁用底层交互
当弹窗出现时,不只是遮罩层要拦截事件,底层内容本身也该“失活”。靠 CSS 的 pointer-events 控制是最轻量、无 JS 干预的方案。
- 别只给遮罩层加样式,同时给 body 或包裹容器加类:
class="mask-active",再配 CSS:.mask-active .page-content { pointer-events: none; } - 避免写死
pointer-events: none在全局样式里——否则关闭弹窗后底层依然点不动 - 兼容性没问题:所有 uni-app 支持的平台(包括 iOS Safari)都支持该属性
遮罩层必须带 z-index 且高于所有内容
很多穿透问题根本不是事件没拦住,而是遮罩层压根没盖住目标元素——用户点的其实是“视觉上被遮住、实际仍在响应”的下层区域。
- 检查遮罩层是否用了
position: fixed或absolute,且z-index≥ 999(常见组件如u-popup默认是 1000+) - 特别留意地图、
cover-view、video等原生渲染组件:它们层级天然更高,普通view遮罩无效,必须改用cover-view或调整结构 - 不要依赖父级
z-index传递——每个定位元素的堆叠上下文是独立的,遮罩层自身必须显式声明z-index
滑动穿透要用 @touchmove.stop.prevent
点击穿透好处理,但用户在弹窗上滑动手指时,底层页面跟着滚动,这是另一个高频问题。它和点击事件无关,得单独拦截触摸移动行为。
- 在弹窗外层容器(比如
<view class="popup-wrapper">)上加:@touchmove.stop.prevent -
.prevent阻止默认滚动,.stop阻止冒泡,两个缺一不可 - 别只对遮罩层加——如果弹窗内容区可滚动(如长表单),需额外处理内部滚动,否则用户无法在弹窗里滑动查看内容

















