需求:实现如图所示的瀑布流布局(左右item宽度相同,但高度不同,形成高度差布局)
分析:
1. 每个item由一张图片和下方的文字构成
2. 通过改变图片的高度,实现整体item的高度差
实现方式:
1.获取列表
2. 遍历,随机生成一定高度范围内的数组,将"height:xxxpx;"的style样式,给每一个img标签
3. 声明两个变量:左侧总高度,右侧总高度
4. 遍历,if左侧总高>=右侧总高,item应分配在左侧,否则,item分配在右侧
5. item样式均设置为absolute,分在左侧是left:0,右侧为right:0,top值通过计算获得
6. 第一个item:"left:0;top:0;",更新左侧总高 += item1.offsetHeight + 两个item上下间隔距离 +‘px’
第二个item:"right:0;top:0;",更新右侧总高 += item2.offsetHeight + 两个item上下间隔距离 +‘px’
第三个item:"left:0;top: 左侧总高;",更新左侧总高 += item3.offsetHeight + 两个item上下间隔距离 +‘px’
以此类推...
7. 所有item的样式,存放在数组中,用于布局
参考代码
<template>
<div class="goods">
<div class="goods-item" v-for="(item,index) in goodsData" :key="index" :style="goodsStyles[index]">
<img :src="item.img" :style="imgHeightStyles[index]" >
<div class="goods-item-desc">
<p class="goods-item-desc-title text-line-2" >{{item.name}}</p>
<div class="goods-item-desc-detail">
<p class="goods-item-desc-detail-price">¥ {{item.price}}</p>
<p class="goods-item-desc-detail-stock">销量: {{item.volume}}</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'goods',
data () {
return {
MIN_IMG_HEIGHT: 178,
MAX_IMG_HEIGHT: 230,
goodsData: [],
imgHeightStyles: [],
goodsStyles: [],
leftHeightTotal: 0,
rightHeightTotal: 0
}
},
mounted () {
this.initData()
},
methods: {
// 初始化商品列表
initData () {
this.$http.get('/goods').then(data => {
this.goodsData = data.list
console.log(this.goodsData)
// 生成图片高度数组
this.getImgHeights()
// 排列
this.initLayout()
})
},
getImgHeights () {
this.goodsData.forEach(element => {
this.imgHeightStyles.push({
height: this.imgHeight() + 'px'
})
})
console.log(this.imgHeightStyles)
},
/**
* 返回随机的图片高度
*/
imgHeight: function () {
const result = Math.floor(Math.random() * (this.MAX_IMG_HEIGHT - this.MIN_IMG_HEIGHT) + this.MIN_IMG_HEIGHT)
return result
},
initLayout () {
// DOM更新后才能设置布局
this.$nextTick(() => {
var elementList = document.getElementsByClassName('goods-item')
console.log(elementList)
elementList.forEach(ele => {
console.log(ele)
// 1.判断排列在左侧/右侧
if (this.leftHeightTotal <= this.rightHeightTotal) {
// 左侧
this.goodsStyles.push('left:0px;top:' + this.leftHeightTotal + 'px;')
// 2.获取item的高度
this.leftHeightTotal += ele.offsetHeight
// 3.加上margin的距离,更新总体高度
this.leftHeightTotal += 12
} else {
// 右侧
this.goodsStyles.push('right:0px;top:' + this.rightHeightTotal + 'px;')
this.rightHeightTotal += ele.offsetHeight
this.rightHeightTotal += 12
}
})
})
}
}
}
</script>
<style lang="scss" scoped>
@import '@css/style.scss';
.text-line-2{
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.goods{
position: relative;
margin:$marginSize;
}
.goods-item{
position: absolute;
width: 49%;
padding: px2rem(5);
background-color: #fff;
box-sizing: border-box;
border-radius: $radiusSize;
img{
width:100%;
}
&-desc{
width: 100%;
font-size: $infoSize;
overflow: hidden;
&-detail{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: px2rem(5);
&-price{
color: red;
}
&-stock{
color: silver;
text-align: right;;
}
}
}
}
</style>