实现瀑布流的几种方式和缺点

467 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

前文:本片文章主要讲解瀑布流的实现思路和问题,并不会有相关代码。

1. 什么是瀑布流?

简单来说就是一些图文结合像是以瀑布流一样的流水式布局,例如:

image.png

这就是一个典型的瀑布流构局: 我们可以看到瀑布流首先又一下几点

  1. 瀑布流是由一小块一小块的图片,或者文字组合起来的一个小模块,然后这些小模块又组合成了大模块
  2. 我们看可以看到这些模块其实又一些地方是不太规律的,比如高度参差不齐
  3. 但是我们又可以看到一些相似的地方,比如图片的宽度,图片都好像是一列一列的,间隙几乎是一样的。

那么我们就可以将具有这类规律的图片,称之为瀑布流

2. 实现瀑布流的方式:

实现瀑布流其实有好几种实现方式,在这里我会列举两种实现瀑布流的方式

1. 列式布局(管道模式)

首先,我们可以把瀑布流整体堪称是N列 每一列我们都要往里面添加图片, 我们先给每一列都添加一个图片,我们可以计算出每一列的高度 然后向最短的一列添加一张图片,每添加一列,我们都在此对比,之所以要对比,是因为我们不能确定最短的那一列,在添加照片后是否仍然是最短的那一列。然后,直到我们把数据全部排列完毕:

image.png

但是这样的排列方式是不完美的,并且如果我们使用了vue 的v-for 会有很严重的问题,例如, 我们肯定要对数组进行切割,切割成我们需要的列数,这样首先会增加一部分的计算量,还会对数组进行切割, 这还不是问题的关键,如果我们这样做了,切割成N个数组,或者一个二维数组,那么v-for在渲染的时候就会按照列来进行渲染,就会造成我加载完第一列再加载第二列,这样显然再页面中呈现的效果是非常不好的。

image.png

2. 定位布局(定位模式)

首先,我们要从整体来看,我们想象所有的这些模块是放在一个父级div中,父级div为相对定位,然后这个父级div里面放了N个这种小模块,每个模块都是绝对定位,通过绝对定位来找准自己的位置,:同样的,这里我们也可以和列式布局一样,我们先确定第一行的div的left和top,第一行的top 肯定是0 或者一个定植,那么我们就只需要关心他们的left了,第一张的left肯定是0 或者是空隙的值,那么第二张图就是第一张图的空隙或者0+第一张的图的宽度,加上第二张图的空隙,一以此类推,我们将第一行的图片的left和top就都可以确定了,那么剩下的就十分的简单了,我们只需要知道第一列的n张图,那一张图最短就代表着这一列是对短的,那么我们就往其中加上一张图,那么这一列的高度。就再加上一个空隙和添加进来的那张图片的高度就好了,以此类推,我们可以得到所有图片的top值和left值,然后我们可以这两个值作为对象添加到数组数据中的每一个数据中,使他们都具备left和top值,然后我们通过v-for循环,不用切割数组,直接一口气进行渲染,

image.png

这样做不好的地方就在于,首先我们需要后端为我们提供每一张照片到width和height,或者我们自己获取也行,然后通过大量的计算,从而才能得到left值,非常耗费性能,而且如果一旦需要改变宽度或增加列数,就又需要重新计算,但好处也显而易见,就是这样不会造成列式布局所带来的困扰,并且如果进行优化,以上的代价会小很多