是唯一能真正防 ios 点击穿透的蒙层方案,因 ios 小程序原生渲染层不拦截 touch 事件,而 mask 组件底层走原生视图合成,可可靠捕获并吞掉所有穿透操作。

<mask></mask> 是唯一能真正防 iOS 点击穿透的蒙层方案,用 <view></view> 加透明背景在小程序里点一下就穿到下层,白屏或报错都算轻的。
为什么必须用 <mask></mask> 而不是 <view></view>
iOS 小程序原生渲染层对 <view></view> 遮罩不拦截 touch 事件,哪怕加了 @touchmove.stop.prevent 和 pointer-events: none 也大概率失效;<mask></mask> 是 uni-app 提供的专用遮罩组件,底层走原生视图合成,能可靠捕获并吞掉所有穿透操作。
常见错误现象包括:点击蒙层后触发背后按钮、滑块验证码拖拽时意外跳转、弹窗未关闭但页面已响应滚动。
- 仅在微信小程序、支付宝小程序、iOS App(vue 模式)中必须强依赖
<mask></mask> - H5 和 Android App(vue 模式)可用
<view></view>+z-index+position: fixed应急,但跨端一致性差 - nvue 下不支持
<mask></mask>,需改用<cover-view></cover-view>或<cover-image></cover-image>组合
<mask></mask> 的正确写法与关键属性
蒙层必须包裹在弹窗容器外层,且不能嵌套在 scroll-view 或 swiper 内部,否则在某些平台会丢失事件绑定。
最小可行结构:
<view class="slide-dialog" v-show="visible"><mask :show="visible"></mask><view class="popup-content"><!-- 自定义内容 --></view></view>
-
:show必须双向绑定布尔值,不能只靠v-show控制显隐 -
@click直接写在<mask></mask>上,不要代理到父<view></view> - 不要给
<mask></mask>设style,它的背景色由background-colorprop 控制(uni-app 3.4+ 支持) - 旧版 uni-app 若无
background-colorprop,需配合<view></view>叠加一层半透背景(仅限非 iOS 场景)
蒙层点击关闭的兼容性处理
安卓和 H5 下 <mask></mask> 点击正常触发,但微信小程序真机调试常有 100–300ms 延迟,发布包无此问题;若业务要求“立即响应”,得加防抖:
handleMaskClick() {
if (this.isClosing) return
this.isClosing = true
this.visible = false
setTimeout(() => { this.isClosing = false }, 300)
}
- 避免连续快速点蒙层导致
visible来回切换 - 不建议用
uni.showToast或uni.showModal替代自定义蒙层——它们根本不支持嵌入内容,强行塞进去会报Cannot read property 'draw' of null - 如果弹窗内含
video、ad、地图等原生组件,<mask></mask>无法覆盖,此时只能降级为 nvue 方案或调整布局避开原生组件区域
蒙层看着简单,但跨端行为差异藏在底层渲染逻辑里。最易被忽略的是:iOS 小程序里,哪怕你写了 @touchmove.stop.prevent,只要没用 <mask></mask>,用户手指划过去就穿了——这个坑没法靠 CSS 或 JS 补救。











