最可靠方式是按端区分处理:App端用pages.json设"bounce": "none",H5端用overscroll-behavior或JS控制body滚动,小程序端必须用@touchmove.stop.prevent事件拦截。直接禁用页面滚动,最可靠的方式是**按端区分处理**:App 端靠 `pages.json` 配置,H5 端靠 CSS 或 JS 控制,小程序端则必须用事件拦截。混用方案反而容易失效或引发卡顿。
pages.json 中禁用 App 端弹性滚动(iOS/Android)
这是 app 端最干净、无副作用的方案,直接关掉系统级 bounce 行为,不依赖 js 也不影响性能。
-
pages.json中对单页禁用:"bounce": "none"必须写在"app-plus"下,且只对原生渲染生效 - 全局禁用写在
"globalStyle"里,但要注意:若某页内有scroll-view,需单独给它设scroll-y="true",否则内容不可滚动 - 不支持微信小程序或 H5,写了也无效;仅对打包成 App 的版本起作用
H5 端用 overscroll-behavior 或 body.style.overflow
H5 没有 bounce 配置项,得靠 CSS 或 JS 干预。但注意:document.body.style.overflow = 'hidden' 会清空整个页面滚动条,包括弹窗内部可滚动区域——除非你同时控制了子容器的 overflow-y: auto。
- 推荐优先用
body { overscroll-behavior: none; },它只禁弹性回弹,不影响正常滚动 - 若需临时禁用(比如弹窗打开时),务必在关闭时恢复原值,不要只设空字符串:
document.body.style.overflow = ''可能继承父级样式,建议存原始值再还原 - 绑定
touchmove事件并调用preventDefault()必须加{ passive: false },否则 iOS Safari 会忽略并报警告
小程序端只能靠 @touchmove.stop.prevent 拦截
微信/支付宝等小程序不支持修改 body 或 page 样式来禁滚动,也不能监听全局 touchmove。唯一可行路径是:在遮罩层或弹窗根节点上加事件拦截。
- 必须用 Vue 模板语法
@touchmove.stop.prevent,不能在 JS 里手动绑事件,否则小程序环境不触发 -
.stop防止冒泡到 page,.prevent阻止默认滚动,两个缺一不可 - 如果遮罩层是
uni-popup,直接写在组件标签上即可:<uni-popup></uni-popup>;自定义遮罩则需确保该view覆盖全屏且层级足够高
scroll-view 内部滚动与页面滚动的边界问题
很多人以为加了 scroll-view 就自动隔离滚动,其实不然:如果外层 page 或 view 本身可滚动(比如没设 height 或 overflow: hidden),scroll-view 滚到底后仍会触发页面滚动。
- 确保
scroll-view父容器有明确高度(如height: 100vh)且overflow: hidden - App 端若还出现“滑过头”的弹性效果,说明
pages.json里没配bounce: none,CSS 无法覆盖系统行为 - 小程序中
scroll-view滚动到底部时松手,有时仍会轻微拖动页面——这是底层 WebView 行为,只能靠遮罩层事件拦截兜底
pages.json,H5 端用了 passive 默认值,小程序端绑了 JS 事件却没走模板语法。三端逻辑不统一,就很容易漏掉某一种情况。











