日常业务需求中经常会使用到瀑布流布局,在实现瀑布流布局时,总体上的思路是:将页面等分为一定的列数,计算出最短的一列,然后将需要放入的元素放入最短的一列中,重复以上步骤,直到最后将所有元素放入列中。
总体来数,瀑布流布局的计算步骤比较复杂,同时还需要考虑上拉刷新等情况,为了减少重复的工作量,可以创建一个瀑布流的组件,后续在开发时只需要关注每一个元素的布局,而无需考虑瀑布流的实现,从而大大的减少工作量。
实现效果:
组件使用示例
// 引入组件
import waterfall from '@com/waterfall'
// 注册组件
components: {
waterfall
}
// HTML
<waterfall :cols="2" :dataList="list" @loadmore="loadmore" @scroll="scroll">
<div class="list-item" v-for="(item, index) in list" :key="index">
<div class="index">{
{
index}}</div>
<img v-if="item.img" class="img" :src="img" alt="">
<div class="title" v-if="item.title">{
{
item.title }}</div>
</div>
</waterfall>
组件实现思路:
- 组件下创建一个slot插槽,开发时将要进行瀑布流布局的元素放入插槽中;
- 根据瀑布流布局的列数在父组件下创建对应数量的div,通过float:left或是flex布局将这些div分布为多栏布局;
- 计算每一栏的高度,获取最矮的一栏;
- 将slot插槽中的元素一个个的放入最矮的一栏中;
- 重复3,4步骤,直到所有的元素都布局完毕。
注意点:
- 在计算每一栏高度的时候需要考虑到图片加载比较慢的问题,有可能计算的时候图片还没有加载出来,因此图片的高度未计算在内,导致计算不准确。解决方案是,先计算出图片的高度,通过style设置图片高度,进行占位。
- 上拉加载更多的情况:数据长度会变化,需要继续渲染新的元素,因此需要记录下已渲染的部分。
- 图片懒加载:图片懒加载通过指令的方式实现(实现方式见这里,获取图片src时需要考虑懒加载的情况。
组件实现代码
github地址:https://github.com/377-dsq/ddcom/tree/master/
HTML部分只需要加一个slot插槽放入需要布局的元素,布局完成后可以通过this.$slots.default获取到元素。
<!--HTML部分-->
<template>
<div class="com-waterfall" ref="root">
<div class="slot-box">
<slot></slot>
</div>
</div>
</template>
js部分:
<script>
export default {
name: 'com-waterfall',
props: {
// 列数
cols: {
type: Number,
default: 2
},
// 数据列表
dataList: {
type: Array,
default: () => {
return []
}
},
// 每一列的宽度
width: Number,
// 距离底部多远进行上拉刷新
reachBottomDistance: {
type: Number,
default: 100
},
// 滚动节流间隔事件,ms
interval: {
type: Number,
default: 100
}
},
data() {
return {
root: null