必须在 pages.json 中显式配置 enablePullDownRefresh: true,否则 onPullDownRefresh 不触发;H5 不支持原生下拉,需用 scroll-view 模拟;onReachBottom 失效多因滚动容器被样式截断;长列表操作应避免全量赋值,改用 push 和 nextTick;状态管理须闭环,平台差异需针对性处理。

必须在页面 pages.json 中显式开启 enablePullDownRefresh: true,否则 onPullDownRefresh 函数完全不会触发——这是 80% 刷新失效的根源。
页面配置必须写对位置,不能只靠 JS 写函数
uni-app 不是「写了 onPullDownRefresh 就能拉」,它依赖原生层的下拉开关。这个开关只认 pages.json 里对应页面的 style 节点:
-
enablePullDownRefresh必须设为true(默认是false) - 若该页面在
tabBar或全局pages.json中被覆写为false,单页配置会被覆盖 - H5 端原生不支持该特性,即使开了也无效;必须用
scroll-view+@pulling-down模拟 - App 端 nvue 页面不支持
onReachBottom,只能用scroll-view的@scrolltolower
onReachBottom 触发失败?先检查滚动容器是否「真可滚」
常见现象:列表内容明明超过一屏,但滑到底部就是不进 onReachBottom。根本原因是 uni-app 默认页面不是滚动容器——它只在「内容自然撑高且未被截断」时才启用页面级滚动监听。
- 根容器加了
height: 100vh、position: fixed或overflow: hidden→ 滚动被截断,触底失效 - 列表外层套了
view但没设display: block或flex-direction: column→ 渲染高度为 0 - 内容不满一屏 → 根本不会触发(和微信原生逻辑一致,非 bug)
- 解决办法:删掉所有限制高度的样式;或改用
scroll-view并显式设height和scroll-y
数据操作别直接赋值,小心响应式爆炸和虚拟滚动错位
长列表(尤其 >100 条)下,this.list = [] 或 this.list = this.list.concat(newData) 会触发 Vue 全量 diff,卡顿明显;若用了虚拟滚动,还会导致 scrollTop 计算失准、白屏或重复渲染。
- 下拉刷新清空:用
this.$nextTick(() => { this.list = []; }),避免 setData 冲突 - 上拉加载追加:用
this.list.push(...newData),而非重建数组 - 分页参数必须同步重置:
onPullDownRefresh里设this.pageNum = 1,onReachBottom里this.pageNum++ - 每次加载后必须校验
newData.length < pageSize来判断是否到底,不能只靠后端hasMore字段
状态管理要闭环,别让 loading 卡死或静默失败
用户下拉后界面无反馈、上拉后一直转圈、失败后没提示——90% 是状态没管住。
- 下拉时调用
uni.startPullDownRefresh()(兼容 H5),并在onPullDownRefresh结尾必加uni.stopPullDownRefresh() - 上拉前加守卫:
if (this.loading || this.noMore) return - 网络失败必须显式通知:
uni.showToast({ icon: 'none', title: '加载失败' }),不能只 console.error -
uni.hideNavigationBarLoading()已废弃,别再用
最易被忽略的是平台差异:小程序触底距离设 150 更稳,H5 必须换 scroll-view,nvue 页面连 onReachBottom 都不认——这些不是“多试几次就能好”的问题,而是架构层面的硬约束。


















