uni-app 中真瀑布流需用 js 动态控制列高,推荐 vue-waterfall-easy;须关闭默认懒加载、手动触底加载、用唯一 key、图片预取尺寸并本地缓存,避免 ios 滚动与图片解码耦合问题。

uni-app 里用 uni-col 或 CSS Grid 做不了真瀑布流
uni-app 官方组件库没有原生瀑布流容器,uni-col 是等高栅格,display: grid 在小程序端(尤其是微信)不支持 grid-template-rows: masonry,强行用 column-count 会导致图片错位、事件绑定失效、滚动监听不准。真瀑布流必须靠 JS 控制列高 + 动态插入。
推荐方案:用 vue-waterfall-easy + 自定义 slot 渲染
这个库专为 uni-app 优化过,不依赖 DOM 高度测量(避免 H5 和小程序差异),通过维护两列高度数组来决定下一项插哪列。关键是要关掉默认图片懒加载,改用 uni.$on('scrolltolower') 手动触底加载。
- 安装:
npm install vue-waterfall-easy --save - 在页面中注册:
components: { WaterFall },别用全局注册(uni-app 的 components 生命周期容易出问题) - data 里初始化两列数组:
columns: [[], []],每次 push 新 item 到较短列 - 图片必须设固定宽高比或用
uni.getImageInfo预取尺寸,否则首屏会闪动
uni-app 瀑布流最常踩的三个坑
不是写法不对,是平台限制没绕过去:
-
scroll-view的scrolltolower在 iOS 微信里经常不触发——得加lower-threshold="50"并手动uni.createSelectorQuery()检测底部距离 - 列表项里用
v-for直接遍历二维数组(如columns[0])会导致响应式丢失——要用computed合并成一维数组再渲染 - 每个 item 的
key如果只用index,图片加载完成时会重排——必须用唯一id,且不能是后端返回的原始 id(要拼上列索引,如item.id + '-' + columnIndex)
性能敏感点:图片加载和虚拟滚动要不要上?
100 条以内不用虚拟滚动,反而增加复杂度;但图片必须走 uni.downloadFile + 本地缓存路径,禁用 <image src="https://..."></image> 直连。微信小程序对远程图并发数有限制,瀑布流里同时加载 20+ 张图会卡顿甚至白屏。
- 缓存逻辑写在
onLoad里,用uni.getStorage查路径,命中就直接赋值给item.cachedImg - 没命中才调
uni.downloadFile,成功后uni.saveFile并更新item.cachedImg - 别用
uni.previewImage的原始数组——它要求所有图都是本地路径,瀑布流里混着远程图会 crash











