onReachBottom 不触发的根本原因是滚动容器未形成真实滚动;常见于样式截断滚动流、内容不满一屏或平台不支持,需按平台差异配置或改用 scroll-view。

onReachBottom 不触发?先看滚动容器有没有真滚动
根本原因不是代码写错了,而是 uni-app 的 onReachBottom 只监听「页面级滚动」,且前提是内容自然撑高、超出视口。一旦被样式截断,它就彻底静默。
常见失效场景:
-
page根节点或外层<view></view>加了height: 100vh、position: fixed或overflow: hidden→ 滚动流被掐断 - 列表外层没设
display: block或flex-direction: column→ 渲染高度为 0 - 内容不满一屏(比如只有 3 条数据)→ 触底逻辑根本不启动,和微信原生一致,非 bug
验证方法:在 onReachBottom 开头加 console.log('triggered'),真机滑到底没输出,基本就是滚动未激活。
pages.json 配置 onReachBottomDistance 怎么设才稳
这个值不是越小越好,不同平台感知差异大:小程序(尤其 iOS 微信)对距离敏感度低,设 50 常常要多拉 100px 才触发;H5 端压根不走这个生命周期;App 的 nvue 页面也不支持。
实操建议:
- 小程序平台统一设为
"onReachBottomDistance": 150(实测更可靠) - H5 和 App(nvue)必须弃用
onReachBottom,改用<scroll-view scroll-y></scroll-view>,并显式设置height - 不要在全局
pages.json里统一配,务必按单页配置,否则会被 tabbar 或 style 覆盖
数据追加别用 this.list = [...],小心卡顿和错位
长列表(>100 条)下,this.list = this.list.concat(newData) 或 this.list = [...this.list, ...newData] 会触发 Vue 全量 diff,滚动掉帧明显;若用了虚拟滚动,还会导致 scrollTop 计算失准、白屏或重复渲染。
正确做法:
- 上拉加载时用
this.list.push(...newData)—— 复用原数组引用,最小化响应式开销 - 加载前必须校验:
if (this.loading || this.noMore) return,防止快速滑动多次触发 - 每次请求后检查
newData.length 来判断是否到底,别只信后端 <code>hasMore字段(总数可能动态变化)
状态管理漏一步,loading 就永远卡住
很多人设了 this.loading = true 就不管了,结果网络失败或接口超时,UI 一直转圈,用户以为卡死。
关键守卫点:
- 请求发起前设
this.loading = true - 成功/失败回调里都必须恢复
this.loading = false - 后端返回空数组或
length === 0时,同步设this.noMore = true,避免无限白屏等待 - 下拉刷新时记得重置分页参数:
this.pageNum = 1,上拉时再this.pageNum++
最易忽略的是:H5 端 uni.stopPullDownRefresh() 无效,但调用无害;而 uni.hideNavigationBarLoading() 已废弃,千万别用。


















