背景
瀑布流是大家日常开发过程中经常遇到的一个场景,我们公司内部的组件库中也提供了一些解决方案。但这些方案适用场景都很单一,且每个实现方案都或多或少存在一些问题,基于此,我们设计与开发了一个兼容多场景的瀑布流组件。
目前转转展示商品流时会采用三种布局方式:分别是卡片流、固定式瀑布流、交错式瀑布流。
其中卡片流以一个下拉列表的形式呈现。这种布局可以让用户专注于单个列表项,有利于阅读。主要应用于转转的二级列表页入口,效果如下
固定式瀑布流图片区域大小高度保持不变。统一的高度会使整个界面看起来比较整齐,视觉上不乱。主要应用于一些频道页场景,效果如下
交错式瀑布流视觉表现为宽度相等、高度不定的元素组成参差不齐的多栏布局,转转的首页以及商详推荐页面会选择以这种方式来做承载
现有方案的问题
以上三种场景中,第一种和第二种场景图片高度固定,实现相对简单,直接使用无限加载 List 组件即可。经常出问题的是第三种场景:交错式瀑布流。这种场景下需要等图片加载完后,获取到图片高度,再添加到瀑布流的最低列,否则会影响最低列的计算,从而出现长短不一的列。
转转公司内部针对交错式瀑布流的实现主要有以下几种方案
方案 1:采用左右两栏布局,先左右均分第一页瀑布流数据并进行渲染。等到第二页数据渲染时,会先将第二页第一个数据取出并渲染到最低列,并且进行
IntersectionObserve
监听,等到该元素出现在视窗内,再从数据源中取出第二个数据并添加到新的最低渲染列中,如此顺环往复实现懒加载的瀑布流优点:采用
IntersectionObserve
实现瀑布流的懒加载,逻辑实现简单缺点:
分栏布局只支持两栏,不支持参数配置多列;
第一页数据不符合瀑布流的规范,有概率出现一列长,一列短的情况;
IntersectionObserve
的兼容性问题;没有暴露数据加载完毕的事件,这样在配合无限加载组件时,容易出现下拉请求两次接口的问题
方案 2:采用宽度百分比进行样式布局,首屏渲染就开启IntersectionObserve
监听,元素出现在视窗后,设置一个setTimeout
加载下一个瀑布流元素,同时在该 dom 上添加一个属性标识,防止二次触发。
优点: 支持参数配置多栏布局,首屏符合瀑布流的规范,同时暴露了瀑布流加载完毕后的事件,配合无限加载时不会出现两次请求接口的问题
缺点:
IntersectionObserve
的兼容性问题依旧没有解决;内部 DOM 查询、操作频率较高;耦合无限加载 List 的逻辑,维护成本较高;setTimeout