无感下拉刷新的关键是不阻塞主线程、不触发整页重排、不重复高开销操作;pages.json中enablePullDownRefresh必须配在页面style内,onPullDownRefresh内仅重置分页、调用加载、必调stopPullDownRefresh;列表需用稳定key(如item.id+页码),图片用IntersectionObserver控制加载并及时销毁实例。

下拉刷新本身不可能“无感”,但用户感知不到卡顿、不看到白屏或闪动、不察觉数据重绘,就是实际意义上的无感。关键不在动画多酷,而在不阻塞主线程、不触发整页重排、不重复执行高开销操作
pages.json 配置必须一次写对
enablePullDownRefresh: true 必须写在对应页面的 style 里,不是 globalStyle,也不是 manifest.json 或 Vue 文件里。漏配或错放位置,onPullDownRefresh 根本不会被调用——连 console.log 都不会执行。
- 配完必须重启 H5 / 小程序项目,热更新不生效
- 建议同步加
backgroundTextStyle: "dark",否则微信小程序下拉文字可能透明不可见 - 安卓某些机型(如 OPPO)会因滚动惯性多次触发
scrolltolower,但onPullDownRefresh是框架生命周期,更可控
onPullDownRefresh 里只做三件事
这个函数是入口,不是执行体。它被调用时,UI 动画已启动,你只有「开始干活」的义务,没有「自动收工」的保障。
- 重置分页参数(如
this.pageNum = 1) - 调用真实的数据加载方法(如
this.refreshData()),别把请求逻辑全塞进去 - 无论成功失败,最后必须调
uni.stopPullDownRefresh(),否则动画卡死,用户再下拉也没反应
常见错误:在 try/catch 外层没包 finally,导致接口超时或报错后忘记 stop;或者在 onLoad 里误调 uni.stopPullDownRefresh(),完全无效。
列表渲染必须用稳定 key + 防止整列重绘
Vue 2(uni-app 当前主力版本)不支持 <template v-for> 上写 key,所以 key 必须落到每个子项节点上,且不能是 :key="index"。
-
item.id必须来自后端,全局唯一;若后端没给,至少拼上页码::key="item.id + '_' + this.pageNum" - 不用唯一 key 会导致分页后索引重复,Vue 错误复用组件实例,表单状态、图片加载状态全乱
- 真机调试时打开性能面板,看 Layout 和 Paint 时间——key 生效后这两项会明显下降
图片加载别信 lazy-load,用 IntersectionObserver 控制时机
<image lazy-load> 在 H5 和小程序行为不一致,且无法控制预加载距离。真正可控的方式是手动创建观察器:
- 每个图片容器(比如
<view class="img-wrapper">)初始化一个uni.createIntersectionObserver -
rootMargin: '200px 0px'是经验值,提前 200px 开始加载,兼顾 4G/WiFi 场景 - 回调中设置
img.src后立即observer.unobserve(img),避免重复触发 - 加防抖:用
Set记录已加载 ID,if (this.loadedImgs.has(id)) return
最易忽略的一点:IntersectionObserver 实例必须及时销毁,否则内存泄漏,滑动越久越卡——尤其 iOS 小程序真机上表现明显。


















