瀑布流卡顿根源在于scroll高频触发、未节流的uni.createSelectorQuery()或setData、key失效导致整列重绘。应改用onReachBottom、唯一key、IntersectionObserver懒加载并及时销毁观察器。

uni-app 瀑布流分页加载卡顿的根源在哪
不是数据量大就一定卡,真正拖慢渲染的是 scroll 事件高频触发 + 每次都执行 uni.createSelectorQuery() 或反复 setData 大量节点。瀑布流组件(比如 uni-col + uni-row 拼的)一旦没做节流、懒加载或虚拟滚动,页面滑动时 CPU 占用飙升,iOS 尤其明显。
用 onReachBottom 替代 scrolltolower 防止误触
scrolltolower 在某些安卓机型(尤其 OPPO、vivo)上会因滚动惯性多次触发;而 onReachBottom 是 uni-app 生命周期钩子,由框架控制触发时机,更稳定可靠。
- 在
pages.json中确保对应页面启用了下拉刷新和触底加载:"onReachBottomDistance": 50 - 在页面
onReachBottom方法里只做「是否允许加载」判断,不直接发请求:onReachBottom() { if (this.loading || this.hasMore === false) return; this.loading = true; this.loadMore(); } - 请求成功后重置
this.loading = false,并根据接口返回更新this.hasMore
瀑布流列表必须用 key + track-by 控制重绘范围
uni-app 的 v-for 渲染瀑布流时,若不指定唯一标识,新增一页数据会导致整列重新 diff,UI 闪动、布局重排频繁。Vue 2(uni-app 当前主版本)不支持 key 在 template 标签上,所以必须落到每个子项节点:
<view v-for="(item, i) in list" :key="item.id" class="waterfall-item"><image :src="item.imgUrl"></image><text>{{ item.title }}</text></view>
-
item.id必须是服务端返回的唯一字段,不能用数组索引i—— 分页后索引会重复 - 如果后端没给 ID,至少用
item.id + page拼接,避免 key 冲突 - 真机调试时打开「性能面板」观察
Layout和Paint耗时,key 生效后这两项会明显下降
图片懒加载必须关掉 lazy-load 改用 IntersectionObserver
image 标签的 lazy-load 属性在 H5 和小程序表现不一致,且无法精确控制加载时机;uni-app 2.9+ 提供了 uni.createIntersectionObserver,这才是瀑布流图片加载的正确姿势:
- 每个图片容器(如
view.waterfall-img-wrapper)初始化一个观察器,监听其进入视口 - 观察回调中才设置
img.src,并立即销毁该 observer(避免重复触发) - 务必加防抖:同一张图可能被多次进入/退出触发,用
if (this.loadedImgs.has(id)) return去重 - 不要在
onLoad后再调setData更新图片状态——直接改img.src即可,setData只用于业务状态(如 loading 图标)
瀑布流真正的瓶颈不在「怎么加载」,而在「怎么不让它重绘」。key 写错、observer 不销毁、滚动事件没节流,这三处任何一个出问题,优化就归零。真机测的时候别光看「能不能加载」,得盯着 FPS 和内存曲线看。











