小程序实现无限瀑布流

实现瀑布流

实现效果

http://media.kitebear.cn/ct/2019-03-17-2019-03-17%2013.36.04.gif

有好几种方案

1.用column-count属性把页面元素分为俩列或多列来实现

2.用display flex 分列来展示页面

3.比如说用js实现

我今天介绍的就是第三种,因为前两种都会有局限,实现的效果我们希望是左右左右,而不是分成两列去显示,因为如果功能需要列表按照热度显示,从我们视觉来看就是 左右比较好,而不是一整列 1,2,3,4,5…

当然如果你们希望用column-count 实现的话,也可以 请点击,我随便找了一个网址网上有很多,我自己也试过实现起来确实很简单,纯css3实现。

那么好,现在正式开始:

说一下思路,通过js控制两列数组,分别在这两个数组中插入图片实现列表展示

首先HTML布局

<view class="post-content" wx:if="{{list.length}}"> <view class="left-view"> <repeat for="{{leftList}}" key="index" index="index" item="item"> <PostItem :item.sync="item" imgMode="widthFix" /> </repeat> </view> <view class="right-view"> <repeat for="{{rightList}}" key="index" index="index" item="item"> <PostItem :item.sync="item" imgMode="widthFix" /> </repeat> </view></view>

可以看到就是一个外部大壳子,然后两列 left-view、right-view 之后就是两个数组循环展示,PostItem是我自己封装的组件用来展示单个item

css部分

.post-content { padding: 0 24rpx; padding-top: 24rpx; box-sizing: border-box; > view { width: 49%; display: inline-block; vertical-align: top; } .left-view { margin-right: 2%; }}

也很简单两列宽度约等于50%中间有间隔

js部分

loadImages () { setTimeout(() => { const data = this.list let { leftList, rightList } = this if (data.length) { for (let i = 0; i < data.length; i++) { if (data[i].id % 2 == 1) { leftList.push(data[i]) } else { rightList.push(data[i]) } } this.leftList = leftList this.rightList = rightList this.$apply() } }, 1000);}data = { leftList: [], //左列 rightList: [], //右列}

就可以看到下列图

但是如果只是这样实现的话就会有问题,因为它的实现是按照奇偶数实现的,那么如果有几张图片正好很高,那么另外一列就会很难看。

http://media.kitebear.cn/ct/2019-03-17-2019-03-17%2012.28.35.gif

下列有问题的情况

2019-03-17 12.34.53

可以看到左列很难看

那么我做一下修改, 在遍历数据的时候做了左右列表的高度检测,如果那边底那么就append到哪边

loadImages (list) { const newList = list || this.list setTimeout(() => { let { leftList, rightList } = this if (newList.length) { helper.forSetTimeout(newList,async (i) => { const isLeft = await this.isPushLeft() if (isLeft) { leftList.push(newList[i]) } else { rightList.push(newList[i]) } this.leftList = leftList this.rightList = rightList this.$apply() }, 50) } }, 300);}// forSetTimeout 实现function forSetTimeout (list, callback, time = 1000) { for (let i = 0; i < list.length; i++) { setTimeout(((num) => { return callback.bind(null, num) })(i), i * time) }}isPushLeft () { const query = wepy.createSelectorQuery() query.select('.left-view').boundingClientRect() query.select('.right-view').boundingClientRect() return new Promise((resolve, reject) => { query.exec((res) => { const leftData = res[0] const rightData = res[1] resolve(leftData.height < rightData.height) }) })}

最终效果如最上面的图,事实上setTimeout的时间间隔可以改成30毫秒以内,但是我觉得50毫秒已经不影响正常体验了。

相关文章