主题
弹层内 scroll-view 真机无法滚动
现象
- 开发者工具中列表可以滚动。
- 真机中列表能显示,但手指滑动无响应或内容无法完整查看。
- 问题只出现在遮罩、抽屉或底部弹层内部。
原因
catchtouchmove 会拦截 touchmove 事件,常用于阻止弹层打开后背景页面继续滚动。如果绑定该事件的节点同时是 scroll-view 的祖先,内部滚动区域的滑动手势也可能被拦截。
xml
<!-- catchtouchmove 包住整个内容区,内部 scroll-view 可能无法滚动 -->
<view class="mask" catch:touchmove="preventMove">
<view class="sheet">
<scroll-view class="sheet__list" scroll-y>
<view wx:for="{{items}}" wx:key="id">{{item.name}}</view>
</scroll-view>
</view>
</view>开发者工具与真机的触摸事件行为可能存在差异,不能只依据模拟器结果判断。
结构调整
遮罩层与内容层使用兄弟节点。仅在遮罩层绑定 catchtouchmove,不要让它成为可滚动区域的祖先。
xml
<view wx:if="{{visible}}" class="picker-root">
<view
class="picker-backdrop"
catch:touchmove="preventMove"
bindtap="closePicker"
></view>
<view class="picker-sheet">
<view class="picker-sheet__title">选择门店</view>
<scroll-view class="picker-sheet__list" scroll-y>
<view wx:for="{{items}}" wx:key="id" class="picker-sheet__item">
{{item.name}}
</view>
</scroll-view>
</view>
</view>js
Page({
closePicker() {
this.setData({ visible: false })
},
preventMove() {},
})css
.picker-root {
position: fixed;
inset: 0;
z-index: 1200;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.picker-backdrop {
position: absolute;
inset: 0;
background: rgb(0 0 0 / 55%);
}
.picker-sheet {
position: relative;
z-index: 1;
background: #fff;
}
.picker-sheet__list {
height: 50vh;
}排查
- 从
scroll-view向上检查祖先节点,确认是否绑定了catchtouchmove。 - 为纵向
scroll-view设置可确定的height,不要只依赖max-height或无法计算剩余空间的flex: 1。 - 固定区域内的长列表优先使用
scroll-view,不要直接套用浏览器端的view + overflow-y: auto方案。 - 检查是否有透明节点覆盖列表,并确认遮罩与内容的
z-index和点击区域。 - 使用真机调试验证滚动、遮罩点击和背景穿透。
通用遮罩组件如果需要同时承载可滚动弹层,应固定采用“遮罩层与内容层分离”的结构,避免将 catchtouchmove 绑定到整个弹层容器。
参考:
