瀑布流即参差不齐的多栏布局,可向下滚动,且随着向下滑动不断加载新的内容
以下是一些实现方式,只提供用于两栏布局瀑布流的简单思路,多栏瀑布流按照思路也可很快实现,自己去想,懒得写了
js实现
利用js计算和填充数据
直接上代码
<view class="content">
<view class="content-left">
<view class="item" v-for="item in listLeft" :key="item.index">{{ item.content}}</view>
</view>
<view class="content-right">
<view class="item" v-for="item in listRight" :key="item.index">{{ item.content }}</view>
</view>
<view class="noShow">
<view ref="list" class="item" v-for="item in list" :key="item.index">{{ item.content }}</view>
</view>
</view>
.content {
padding: 10rpx;
display: flex;
justify-content: space-between;
}
.content-left {
display: flex;
width: calc(50% - 10rpx);
flex-direction: column;
}
.content-right {
display: flex;
width: calc(50% - 10rpx);
flex-direction: column;
}
.item {
padding: 10rpx;
margin-bottom: 10rpx;
border: 1rpx solid #ccc;
}
.noShow {
width: calc(50% - 10rpx);
position: absolute;
left: 10000px;
bottom: 10000px;
}
this.$nextTick(() => {
let elLeftHeight = 0;
let elRightHeight = 0;
this.list.forEach((item,index) => {
if (elLeftHeight > elRightHeight) {
this.listRight.push(item);
elRightHeight += this.$refs.list[index].$el.clientHeight;
} else {
this.listLeft.push(item);
elLeftHeight += this.$refs.list[index].$el.clientHeight;
}
});
});
过程及原理详细解析
css
- 使用flex布局设置一个两栏布局(根据实际开发情况可设置多栏布局),每一栏纵向排列
- 单独设置一个绝对位置的选择器,使其虽然渲染了,但页面上不展示
html
- 利用flex布局(也可其他方式,无所谓)形成一个基本的两栏布局
- 为渲染到页面但因定位不会展示在页面的模块设置ref(也可在js中使用document直接获取,看你喜好)
js
- 分别定义两个空数组用来存储两栏要展示的数据,再将所有数据存放在另一个单独的数组中,渲染到未展示在页面上的绝对定位的模块(为了严谨,需将该模块宽度与两栏布局的每一栏宽度相同),依次可计算每条数据的高度。
- 按照算法思路,设置左右栏高度都为0,遍历数据,对左右栏高度做判断,将数据写入到较低高度的一栏中(相同高度写入左边),写入后将该数据的展示高度添加到该栏中
较优解:grid布局实现
这种方法不需要对数据进行遍历传入渲染,浏览器自动对内容堆叠排放
首先使用grid布局实现两栏(或多栏)布局
vue+uniapp的实现
.content {
padding: 10rpx;
display:grid;
grid-auto-rows: 10rpx;
column-gap: 10rpx;
grid-template-columns: 1fr 1fr;
align-items: start;
}
.content-item {
border: 1rpx solid #000;
padding: 10rpx;
}
<view class="content">
<view class="content-item" ref="content" v-for="item in list" :key="item.index">{{ item.content }}</view>
</view>
this.$nextTick(()=>{
this.list.forEach((item, index) => {
this.$refs.content[index].$el.style.gridRowEnd = `span ${Math.ceil(this.$refs.content[index].$el.clientHeight / 5) + 1}`
console.log(this.$refs.content[index].$el.style.gridRowEnd);
})
})
过程及原理详细解析
css:
- 使用css的grid布局设定基本两栏布局(根据实际开发情况可设置多栏布局)
- 使用align-items: start设定纵向的排列方式为从上到下依次排列
- 使用grid-auto-rows: 10rpx属性设置网格每行高度为10rpx
js:
- 使用ref获取每个内容模块的高度(我用的vue所以使用的是ref,js也可使用document来获取)
- 使用 clientHeight / 5 ,根据每个模块的高度去除以css中设置的每个网格高度(示例代码用的uniapp的单位rpx,clientHeight获取的是px,10rpx==5px),得到这个模块纵向占据网格的数量,
- 使用js向其添加行内样式 grid-row-end: span [Number],该属性设置该模块纵向占据的网格数量,浏览器渲染时会将其自动向下堆叠