关于小程序和APP的瀑布流组件的封装
运行效果 :
不多说上代码 :
<!-- 瀑布流组件 -->
<template>
<view class="water-fall-flow">
<scroll-view class="content" :style="{height : contentH + 'px'}" scroll-y="true" @scrolltolower="loadMore"
lower-threshold="10">
<!--瀑布流布局start-->
<view class="new-list">
<view class="list-left">
<view class="card" v-for="(item, index) in cardListLeft" :key="index">
<image :src="item.cardImg" alt="" mode="widthFix" width="100%" @load="onImageLoad" />
<view class="card-text">
<view>{{ item.cardTitle }}</view>
<view>{{ item.cardText }}</view>
</view>
</view>
</view>
<view class="list-right">
<view class="card" v-for="(item, index) in cardListRight" :key="index">
<image :src="item.cardImg" alt="" mode="widthFix" width="100%" @load="onImageLoad" />
<view class="card-text">
<view>{{ item.cardTitle }}</view>
<view>{{ item.cardText }}</view>
</view>
</view>
</view>
</view>
<view class="noMore" v-if="showNoMore">我也是有底线的!!!</view>
<!--瀑布流布局end-->
</scroll-view>
</view>
</template>
<script>
export default {
props: {
allcardList: {
type: Array,
default () {
return []
}
}
},
data() {
return {
// 左栏card
cardListLeft: [],
// 右栏card
cardListRight: [],
//分别是左右栏的高度
cardLeftHeight: 0,
cardRightHeight: 0,
//作为card的ID
cardListItem: 0,
//实际载入的card的高度
rImgH: 0,
//作为scoll滚动触底,加载更多的标记,防止多次出发事件,1为允许,0为阻止
loadMoreTemp: 1,
//控制底部“我也是有底线view的显示”
showNoMore: false,
// 存放加载好的card
cardList: [],
// 自适应屏幕高度 ,默认高度是800
contentH: 800
}
},
created() {
this.waterfall();
},
methods: {
// 加载图片 同时计算相对应的高度
onImageLoad(e) {
// e为相关照片属性信息
//实际显示的单栏宽度,345upx
let divWidth = 345;
//图片原始宽度
let oImgW = e.detail.width;
//图片原始高度
let oImgH = e.detail.height;
//重新计算当前载入的card的高度
let rImgH = (divWidth * oImgH) / oImgW + 170;
// 判断是否为第一张card
if (this.cardListItem == 0) {
// 第一张card的高度加到左边的高度去
this.cardLeftHeight += rImgH;
//card索引加1
this.cardListItem++;
// 把第二张card添加到右边栏
// this.cardListRight.push(this.cardList[this.cardListItem])
} else {
//card索引加1
this.cardListItem++;
// 判断那边高度低就加到那边
if (this.cardLeftHeight > this.cardRightHeight) {
this.cardRightHeight += rImgH;
} else {
this.cardLeftHeight += rImgH;
}
//根据目前的栏高,把下一张card,push到低的那栏
if (this.cardListItem < this.cardList.length) {
if (this.cardLeftHeight > this.cardRightHeight) {
this.cardListRight.push(this.cardList[this.cardListItem])
} else {
this.cardListLeft.push(this.cardList[this.cardListItem])
}
}
}
//每次载入的card数量设置为4,只有载入完成才允许下一次的scroll触底,触发loadMore
if (this.cardListItem % 4 == 0) {
this.loadMoreTemp = 1;
}
},
waterfall() {
// 先取4条
this.cardList = this.allcardList.slice(0, 4);
// 把第一个加到左边栏
this.cardListLeft.push(this.cardList[0]);
this.cardListRight.push(this.cardList[1]);
//利用uni-APP获取系统信息Api,获取客户端的屏幕高度,设置成scoll-view的高度,实现触底事件+
uni.getStorageInfo({
success(res) {
this.contentH = res.windowHeight;
}
})
},
// 加载更多
loadMore() {
// 判断是否允许滚动 loadMoreTemp==1,才允许触发
if (this.loadMoreTemp == 1) {
//防止多次触发
this.loadMoreTemp = 0;
// 定义一个新的数组,存放更新的card数组 ==> 每次滚动加载4条
let newcardList = this.allcardList.slice(this.cardListItem, this.cardListItem + 4);
// 判断是否有有新数据
if (newcardList.length != 0) {
// 新数据加载到cardList后面
this.cardList = this.cardList.concat(newcardList);
//把第一个新数据加到目前更低的栏上,以触发@load="onImageLoad"
if (this.cardLeftHeight > this.cardRightHeight) {
this.cardListRight.push(newcardList[0])
} else {
this.cardListLeft.push(newcardList[0])
}
}
// 判断当当前cardList和allcardList长度相等就代表全部加载完了
if (this.cardList.length == this.allcardList.length) {
this.showNoMore = true;
}
}
}
}
}
</script>
<style lang="scss" scoped>
.new-list {
// clear: both;
// overflow: hidden;
// height: 100%;
margin: 15upx;
display: flex;
justify-content: space-between;
>view {
width: 49%;
// &.list-left {
// float: left;
// }
// &.list-right {
// float: right;
// }
.card {
width: 100%;
background-color: aliceblue;
border-radius: 40upx;
overflow: hidden;
margin-bottom: 15upx;
>image {
width: 100%;
}
}
.card-text {
width: 100%;
padding: 10upx;
>view:nth-child(1) {
font-size: 35upx;
color: brown;
}
>view:nth-child(2) {
font-size: 28upx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp:3;
-webkit-box-orient: vertical;
}
}
}
}
.noMore {
background-color: cornsilk;
color: darkgray;
text-align: center;
height: 50upx;
}
</style>
父组件的调用:
<template>
<view class="app">
<waterfall-flow :allcardList="allcardList"></waterfall-flow>
</view>
</template>
<script>
import waterfallFlow from '@/components/common/waterfallFlow';
export default {
components:{
waterfallFlow
},
data(){
return{
allcardList: [{
cardImg: '../../static/01.jpeg',
cardTitle: '我是第一张图片',
cardText: '来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊'
},
{
cardImg: '../../static/03.jpeg',
cardTitle: '我是第二张图片',
cardText: '来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊'
},
{
cardImg: '../../static/02.jpeg',
cardTitle: '我是第三张图片',
cardText: '来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊'
},
{
cardImg: '../../static/01.jpeg',
cardTitle: '我是第四张图片',
cardText: '来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊'
},
{
cardImg: '../../static/04.jpeg',
cardTitle: '我是第五张图片',
cardText: '来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊来见识我的瀑布流啊'
}
]
}
}
}
</script>
这是我本人第一次写博客,请大家多多指教. —>> 大宝