瀑布流组件
3分钟完整版本
我实现的瀑布流核心是异步队列 + 绝对定位。 布局上:维护列高度数组,每次找最短的列放入新卡片,用 transform: translate3d GPU 加速定位。 稳定性上:因为图片高度不确定,我设计了 layoutQueue 队列,串行等待图片加载完成后再排版,配合超时和错误兜底策略,防止布局错乱。 性能上:shallowReactive 减少响应式开销,防抖处理重排,增量更新避免重复计算。 整个组件的复杂度在于异步高度测量与排版时机的控制。
第一层:方案选型
需要实现瀑布流,市面上的瀑布流都不尽人意,问题很多,比如,没有增量更新,不支持动态增删,性能也一般,使用体验不好。 社区调研需求,发现有很多人需要瀑布流,我就基于这个需求实现了一个瀑布流组件。
瀑布流的核心难点是高度不固定的多列布局。我对比了两种方案:
- 两栏布局,维护两列高度,每次找最短的列放入新卡片;
- JS 计算方案:动态计算位置,支持横向顺序填充,更灵活。 我们业务需要保持数据顺序,所以选了 JS 方案。
设计并实现高拓展性瀑布流组件,解决 UniApp 多端布局一致性难题
- 核心算法:设计队列化异步布局算法,通过 Promise + Watch 机制实现图片加载状态感知,动态计算最短列并放置项目,确保布局紧凑性
- 生命周期管理:监听页面
onShow/onHide事件,实现布局中断与恢复机制。页面失活时清理 Promise 队列和 Watch 监听器,避免内存泄漏;页面恢复时重新触发高度获取,解决 UniApp 快速切换页面导致的布局异常和白屏问题 - 容错机制:设计 5 种错误处理策略(默认高度/占位图/重试/完整降级/跳过),配合超时兜底(默认 3s),确保异常场景下组件可用性达 100%
- 性能优化:采用增量重排策略(追加仅计算新增项,删除批量处理),配合 16ms 防抖和 GPU 加速动画(translate3d),在 500+ 项目场景下重排耗时 < 100ms,流畅度提升 60%
- 工程化设计:通过 provide/inject 实现父子组件解耦,支持动态插入/删除/刷新等 8+ 场景
第二层:核心布局逻辑
布局的核心是维护一个 columns 数组记录每列当前高度:
- 遍历数组找到高度最小的列;
- 计算坐标:top,left,然后加入卡片;
- 更新该列高度;
- 容器高度取所有列的最大值。
- 定位使用
transform: translate3d,开启 GPU 加速,避免回流重绘。
第三层:异步排版队列(核心难点)
瀑布流最大的问题是图片高度不确定。我的解决方案是队列化处理 + 异步等待机制:
- 新 Item 先进入
layoutQueue队列,不立即渲染; - 串行处理:等待图片加载完成(监听
onload),获取真实 DOM 高度后再计算位置; - 设置
maxWait超时机制,防止单张图片阻塞整个队列; - 支持多种错误处理策略:重试、占位图、兜底高度。
这保证了布局的稳定性,不会出现图片加载后卡片跳动或重叠。
第四层:性能优化
- 响应式优化:使用
shallowReactive管理 Item 状态,减少 Proxy 开销; - 防抖重排:列数、间距变化时用
debounce(16ms)防抖; - 生命周期感知+增量更新:加载更多时只计算新增 Item,删除/插入时才重排已有数据;
- 增量重排优化:删除 Item 时,直接从
columns数组中删除,避免遍历所有 Item;插入 Item 时,只计算新增 Item 的位置,避免重排所有 Item。 - 自动加载:容器高度不足视口时自动触发
autoLoadMore。" - 动画使用 transform 代替 top/left 提升性能(硬件加速)
亮点
- 异步排版队列
- 页面生命周期感知 + 增量更新
- 多策略错误处理
- 增量重排优化
- 自动加载机制
- 跨平台处理
第五层:边界处理
- 生命周期适配:监听小程序
onShow/onHide,页面隐藏时中断排版,恢复时继续; - 平台兼容:针对微信、支付宝等小程序做条件编译处理;
- 动态增删:支持 Item 的插入和删除,删除后重新计算剩余项目位置。"
