原创
落魄前端-小陈 2021-09-27 13:22:12 5812 收藏 0
前言:pc端的瀑布流为了兼容,我们需要用js写,如果在移动端,只需用css即可实现,
主要使用到的 css:
column-count -- 列的数量,
column-width --列的宽度,
colum-gap -- 列与列之间的距离
实现步骤:
1.上图我只要两列瀑布流,为了我们能更好的设置瀑布流距离左右两侧的距离相等,我们只使用 column-count 和 column-gap,,设置column-count:2, column-gap:0,
2.设置列宽item,上图中我设置item的宽为330rpx
3.设置了item宽度后,怎么才能使得瀑布流中间,以及距离左右两侧的边距相等呢;我们这里只有两列,也就是只有左,中,右三个间隙,所以用总长减去两个列宽再除以3就得到了每个间隙的距离,上图使用的是小程序,所以间隙的宽度大概为(750 - 330*2)/ 3 = 30rpx; 所以我设置了item的margin-right:30rpx;同时设置父元素.wrap的padding-left:29rpx(留一像素,哈哈),这样就能实现间隙相等了.
4.遇到的问题:会遇到列的顶部不对齐,还有内容出现折断,上一个item的底部出现在下一个item的顶部现象,如下图
解决 折断:
(1)item添加样式 -- overflow: auto; height: 100%; (不推荐)
(2) item添加样式 -- display: inline-block; (推荐)
解决 顶部不对齐:
将margin-bottom改成margin-top即可
5.细节的处理:
图片高度自适应,设置图片的样式为width:100%,height:auto,如果是在小程序,这样不起作用,还需要设置image 的mode属性为 widthFix才行。
至此,瀑布流就实现啦
缺点:就是数据会先排完左边,再排到右边,但是我们实际项目中肯定是上拉加载的数据我们是想平分到左右两边。
那么怎么解决呢。这样就需要下面的另一种办法
(1)将获取的数据根据某个性质来划分成多页,比如我们手机端一般瀑布流就是2列,那么我们就可以将数据根据索引的奇偶性来划分成2列,如下图
let listL = []
let listR = []
axios()
.then(res => {
res.forEach((e,i) => {
i % 2 === 0 ? listR.push(e) : listL.push(e)
})
})
<div>
<ul class="left">
<li v-for="item in listL">{{item}}<li>
</ul>
<ul class="right">
<li v-for="item in listR">{{item}}<li>
</ul>
<div>
或者
<div>
<ul >
<ul class="left">
<template v-for="(item , index)in list">
<li :key="{{item.id}}" v-if="index%2==0">{{item}}<li>
</template>
</ul>
<ul class="right">
<template v-for="(item , index)in list">
<li :key="{{item.id}}" v-if="index%2==1">{{item}}<li>
</template>
</ul>
</ul>
<div>
这样的好处是:
(1)如果采用css3的瀑布流布局,会出现数据先排完左边再到右边的情况,如果是一页还好,如果是多页,这显然是不能接受。而现在这种方法就能避免这个弊端
(2)如果在pc端,我们还可能用到js计算left,top的瀑布流,因为pc端会存在多列。但是pc端这种做法会出现什么问题呢?就是图片是异步加载的,所以给计算带来巨大的困扰,如果想准确计算,那就得提前知道图片的尺寸,这就要在获取数据的时候就要获取图片的尺寸。所以现在先将数据分成多列,然后dom也分成多列,就不用管图片异步加载的问题。