最近有一个需求,用户可以动态切换页面的布局 分别是1.列表布局 2.网格布局 3.瀑布流布局
其中瀑布流是最难实现的一种
1、实现瀑布流的思路
随机生成图片高度,使用absolute布局,使用两个变量来分别记录左边的高度以及右边的高度,当左边的高度大于右边的高度的时候,下一个item就会push进右边,相对应的right为0px,top为右边高度的值。反之则push进左边。效果图如下👇

1.对图片随机在一定范围内生成高度,并且用一个数组来记录生成的高度
/**
* 返回随机的图片高度
*/
imgHeight() {
let result = Math.floor(
Math.random() * (this.MAX_IMG_HEIGHT - this.MIN_IMG_HEIGHT) +
this.MIN_IMG_HEIGHT
);
return result;
},
/**
* 根据随机高度,生成图片样式数据
*/
initImgStyles() {
this.goodsData.forEach(item => {
this.imgStyles.push({
height: this.imgHeight() + "px"
});
});
},
2.通过ref拿到item的clientHeight,并且定义两个变量,一个记录左边的高度,一个记录右边的高度,
当左边高度大于右边高度的时候,下一个item则会放在右边,把最终得出来的记录每一个item的样式数组绑定
在item中,使用绑定时需要传递下表获取对应的style
/**
* 瀑布流布局
*/
initWaterfall() {
let $goodsItems = this.$refs.goodsItem;
if (!$goodsItems) return;
// 左边高度, 右边高度
let leftHeightTotal = 0,
rightHeightTotal = 0;
$goodsItems.forEach(($el, index) => {
let goodsItemStyle = {};
let elHeight = $el.clientHeight + this.itemMarginBottomSize;
if (leftHeightTotal <= rightHeightTotal) {
goodsItemStyle = {
left: "0px",
top: `${leftHeightTotal}px`
};
leftHeightTotal += elHeight;
} else {
goodsItemStyle = {
right: "0px",
top: `${rightHeightTotal}px`
};
rightHeightTotal += elHeight;
}
this.goodsItemStyles.push(goodsItemStyle);
});
this.$forceUpdate();
this.goodsViewHeight =
leftHeightTotal > rightHeightTotal
? leftHeightTotal
: rightHeightTotal + "px";
},
这样子瀑布流就可以实现了,接下来实现的是如何通过参数来动态改变样式来实现不同的布局
1.父组件通过传递不同的参数,来代表不同的样式
2.首先对于页面定义最基本的样式,不同的布局样式我们使用:class来进行动态改变
3.监听父组件传进来的值,来重新初始化布局
1.网格布局,并不需要使用js来进行判断,样式比较简单,如下👇
// ps:笔者使用的是scss预编译
.goods-grid {
position: relative;
margin: $marginSize;
display: flex;
overflow: hidden;
flex-wrap: wrap;
justify-content: space-between;
&-item {
width: 48%;
border-radius: $radiusSize;
margin-bottom: $marginSize;
overflow: hidden;
.goods-item-img {
width: 100%;
}
}
}
grid网格布局图片如下👇

列表布局相对简单,所以就不再这里贴代码了。最后如果你觉得喜欢或者对你有用,记得点赞哦~