Skip to content

瀑布流组件

3分钟完整版本

我实现的瀑布流核心是异步队列 + 绝对定位布局上:维护列高度数组,每次找最短的列放入新卡片,用 transform: translate3d GPU 加速定位。 稳定性上:因为图片高度不确定,我设计了 layoutQueue 队列,串行等待图片加载完成后再排版,配合超时和错误兜底策略,防止布局错乱。 性能上shallowReactive 减少响应式开销,防抖处理重排,增量更新避免重复计算。 整个组件的复杂度在于异步高度测量与排版时机的控制

第一层:方案选型

需要实现瀑布流,市面上的瀑布流都不尽人意,问题很多,比如,没有增量更新,不支持动态增删,性能也一般,使用体验不好。 社区调研需求,发现有很多人需要瀑布流,我就基于这个需求实现了一个瀑布流组件。

瀑布流的核心难点是高度不固定的多列布局。我对比了两种方案:

  1. 两栏布局,维护两列高度,每次找最短的列放入新卡片;
  2. JS 计算方案:动态计算位置,支持横向顺序填充,更灵活。 我们业务需要保持数据顺序,所以选了 JS 方案。

设计并实现高拓展性瀑布流组件,解决 UniApp 多端布局一致性难题

  • 核心算法:设计队列化异步布局算法,通过 Promise + Watch 机制实现图片加载状态感知,动态计算最短列并放置项目,确保布局紧凑性
  • 生命周期管理:监听页面 onShow/onHide 事件,实现布局中断与恢复机制。页面失活时清理 Promise 队列和 Watch 监听器,避免内存泄漏;页面恢复时重新触发高度获取,解决 UniApp 快速切换页面导致的布局异常和白屏问题
  • 容错机制:设计 5 种错误处理策略(默认高度/占位图/重试/完整降级/跳过),配合超时兜底(默认 3s),确保异常场景下组件可用性达 100%
  • 性能优化:采用增量重排策略(追加仅计算新增项,删除批量处理),配合 16ms 防抖和 GPU 加速动画(translate3d),在 500+ 项目场景下重排耗时 < 100ms,流畅度提升 60%
  • 工程化设计:通过 provide/inject 实现父子组件解耦,支持动态插入/删除/刷新等 8+ 场景

第二层:核心布局逻辑

布局的核心是维护一个 columns 数组记录每列当前高度:

  1. 遍历数组找到高度最小的列
  2. 计算坐标:top,left,然后加入卡片;
  3. 更新该列高度;
  4. 容器高度取所有列的最大值。
  5. 定位使用 transform: translate3d,开启 GPU 加速,避免回流重绘。

第三层:异步排版队列(核心难点)

瀑布流最大的问题是图片高度不确定。我的解决方案是队列化处理 + 异步等待机制

  • 新 Item 先进入 layoutQueue 队列,不立即渲染;
  • 串行处理:等待图片加载完成(监听 onload),获取真实 DOM 高度后再计算位置;
  • 设置 maxWait 超时机制,防止单张图片阻塞整个队列;
  • 支持多种错误处理策略:重试、占位图、兜底高度。

    这保证了布局的稳定性,不会出现图片加载后卡片跳动或重叠。

第四层:性能优化

  1. 响应式优化:使用 shallowReactive 管理 Item 状态,减少 Proxy 开销;
  2. 防抖重排:列数、间距变化时用 debounce(16ms) 防抖;
  3. 生命周期感知+增量更新:加载更多时只计算新增 Item,删除/插入时才重排已有数据;
  4. 增量重排优化:删除 Item 时,直接从 columns 数组中删除,避免遍历所有 Item;插入 Item 时,只计算新增 Item 的位置,避免重排所有 Item。
  5. 自动加载:容器高度不足视口时自动触发 autoLoadMore。"
  6. 动画使用 transform 代替 top/left 提升性能(硬件加速)

亮点

  • 异步排版队列
  • 页面生命周期感知 + 增量更新
  • 多策略错误处理
  • 增量重排优化
  • 自动加载机制
  • 跨平台处理

第五层:边界处理

  1. 生命周期适配:监听小程序 onShow/onHide,页面隐藏时中断排版,恢复时继续;
  2. 平台兼容:针对微信、支付宝等小程序做条件编译处理;
  3. 动态增删:支持 Item 的插入和删除,删除后重新计算剩余项目位置。"