真瀑布流在uni-app中必须用JS动态分组+多列flex-column实现,禁用column-count/grid;因三端渲染不一致,取模分列不考虑真实高度致失衡,需维护columnHeights数组按最短列分配、预估宽高防塌陷、scroll-view手动同步高度并显式重置状态。

真瀑布流在 uni-app 里不能靠 column-count 或 display: grid 实现,三端(尤其微信小程序)会忽略、降级或不重排,首屏错位、触底监听失效是必然结果。唯一跨端稳定的路径是:JS 动态分组 + 多列 flex-direction: column + 高度状态手动追踪。
为什么取模分列(index % 2)看起来像瀑布流,实际是假的
这种写法把第 0、2、4… 项塞左列,1、3、5… 塞右列,完全不考虑每张图真实高度。一旦图片宽高比差异大(比如 1:1 和 4:5 混排),两列高度迅速失衡——左列堆到屏幕外,右列还空着半截。
- 这不是样式问题,是分配逻辑没跟上渲染节奏
- 服务端返回的
width和height字段必须参与预估:用height: calc(100% * item.height / item.width)设内联样式,防初始塌陷 - 没服务端宽高时,用
uni.getImageInfo({ src })并发 ≤ 3 预加载,拿到尺寸再插入,比等@load后查 DOM 快且稳
怎么用 JS 动态分配图片到最短列
核心是维护一个列高数组(如 columnHeights = [0, 0]),每次插入新项前找出最小值索引,把该项 push 进对应列,并更新该列高度。
- 分发逻辑必须在
computed或watch中完成二维数组构建(如columns = [[], []]),不能在模板v-for里实时算 - 列数别写死:用
uni.getSystemInfoSync().windowWidth动态算,例如Math.min(3, Math.floor(windowWidth / 150)) - 每张图的父
view必须设min-height: 200rpx,防止初始渲染空白 - 高度修正必须节流:同一列多次更新需防抖,避免频繁
this.$forceUpdate()或setData
scroll-view 的三个致命坑必须避开
scroll-view 是目前 uni-app 唯一能稳定监听滚动触底的容器,但它对样式极其敏感,尤其在小程序里:
- 绝对禁止给子元素设
position: absolute—— iOS 微信里会丢失scrolltolower触发 - 不能设
height: 100vh—— 小程序不识别vh单位,得用height: calc(100vh - 100rpx)(减掉导航栏、TabBar 等实际占用高度) - 子项高度变化后,
scroll-view不会自动重算滚动高度,必须手动调用uni.createSelectorQuery()获取最新内容高度,再setData更新,否则底部留白或触发不了下一页
分类切换或刷新时,columnHeights 必须显式重置
很多人只清空数据源 list 和分列数组 columns,却忘了重置 columnHeights = [0, 0],新数据就会按旧高度叠加——第一张图直接掉出可视区,或者整列空白。
- 每次
list替换(如分类 tab 切换、下拉刷新),都要同步执行this.columnHeights = [0, 0] - 如果用了封装组件(如
),确认它内部是否自动重置;没文档说明的,宁可自己包一层 wrapper 手动控制 - 调试时直接
console.log(this.columnHeights),比盯着 UI 猜“为什么首屏没图”快得多
真瀑布流的稳定性,不取决于 flex 写得多漂亮,而取决于高度状态是否被准确捕获、及时更新、干净重置。图片异步加载带来的高度不确定性,必须由 JS 主动兜底,而不是寄希望于 CSS 自动响应。











