微信小程序解决滚动穿透

文章讲述了如何在Modal中实现内容滚动并阻止背景页面滚动。关键在于使用`catchtouchmove`属性,当Modal内容滚动到边界时,设置数据属性`isNoScroll`为true,禁止页面滚动。通过在mask遮罩层和Modal的scroll-view层应用`catchtouchmove`并结合事件监听,可以实现Modal内部滚动而外部页面保持静止的效果。


modal内容不会产生滚动情况: 给modal最外层元素添加:catchtouchmove="{{true}}"    禁止滚动

modal内容会滚动情况:

<scroll-view 
 scroll-y 
 bindscrolltoupper="bindscrolltoupper" // 滚动到顶部/左边事件
 bindscrolltolower="bindscrolltolower" // 滚动到底部/右边事件
 bindscroll="bindscroll" // 滚动事件
>
<scroll-view>
    
data: {
 isNoScroll: false
},
  
bindscrolltoupper(e) {
  this.setData({
    isNoScroll: true
  })
},
bindscrolltolower(e) {
  this.setData({
    isNoScroll: true
  })
},
bindscroll(e) {
  if(this.data.isScroll) {
    this.setData({
      isNoScroll: false
    })
  }
}

给mask遮罩层添加属性:catchtouchmove="{{true}}" 
给modal中最外层scroll-view层添加:catchtouchmove="{{ isNoScroll }}", 默认为false,  允许页面滚动,当modal滚动到顶部/底部的时候,设置变量isNoScroll为true,禁止滚动,即可实现modal内容滚动,底部body内容不会跟随body滚动

### 微信小程序中禁止滚动穿透解决方案 在微信小程序开发过程中,滚动穿透是一个常见的问题。以下是几种有效的解决方法: #### 方法一:通过 `catchtouchmove` 属性控制 对于简单的弹窗场景,可以通过设置 `catchtouchmove="{{true}}"` 来阻止事件冒泡[^1]。然而,在复杂场景下(如弹窗内部也有可滚动区域),这种方法可能导致内外都无法正常滚动。 为了优化此情况,可以在遮罩层和弹窗外部容器分别绑定不同的逻辑: - 遮罩层添加属性 `catchtouchmove="{{true}}"`。 - 弹窗最外层的 `scroll-view` 添加动态属性 `catchtouchmove="{{isNoScroll}}"`,其中 `isNoScroll` 的初始值为 `false`,表示允许页面滚动;当检测到 modal 已经到达顶部或底部时,将 `isNoScroll` 设置为 `true`,从而禁用背景滚动[^2]。 ```html <view catchtouchmove="{{true}}" class="mask"></view> <scroll-view scroll-y bindscrolltolower="onReachBottom" catchtouchmove="{{isNoScroll}}"> <!-- 弹窗内容 --> </scroll-view> ``` --- #### 方法二:利用数据驱动方式切换滚动状态 通过监听弹窗的状态变化来动态调整页面滚动行为。具体做法是在弹窗开启时设置标志位 `show=true` 并隐藏页面滚动条,关闭弹窗后再恢复默认状态[^3]。 ```javascript Page({ data: { show: false, }, handleDialogOpen() { this.setData({ show: true }); }, handleDialogClose() { this.setData({ show: false }); } }); ``` 配合 CSS 控制溢出效果: ```css .page-container { overflow: {{show ? 'hidden' : 'auto'}}; } ``` --- #### 方法三:借助 `page-meta` 动态修改页面样式 在 uni-app 或其他支持跨端框架的小程序项目中,推荐使用 `page-meta` 组件动态更改整个页面的滚动特性[^4]。这种方式更加灵活且易于维护。 模板部分定义如下: ```vue <template> <page-meta :page-style="'overflow:' + (show ? 'hidden' : 'visible')"></page-meta> <view class="container"> <!-- 页面主体内容 --> </view> </template> <script> export default { data() { return { show: false, // 是否展示弹窗 }; }, methods: { togglePopup() { this.show = !this.show; }, }, }; </script> ``` --- #### 方法四:通过类名管理滚动行为 另一种常见的方式是基于 DOM 结构操作,即通过条件渲染特定样式类名实现滚动锁定功能[^5]。例如,当弹窗可见时向父级视图追加一个固定高度并隐藏溢出的内容。 WXML 文件结构示例: ```html <view class="{{showSearchView ? 'tripList_root' : ''}}"> <view>默认元素</view> </view> ``` 对应 WXSS 定义: ```css .tripList_root { width: 100%; height: 100vh; /* 占满屏幕 */ overflow: hidden; position: fixed; top: 0; left: 0; z-index: 999; } ``` --- 以上四种方案各有优劣,开发者应根据实际需求选择最适合的一种或者组合多种策略解决问题。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值