在小程序的开发过程中,遇到了这样的功能需求:在保持瀑布流布局的情况下,使用懒加载来渲染页面,并且要求对其中的属性添加排序功能。
单独拿出来都是很好实现的功能,但是当三个功能联系在一起时,问题就出现了。
最开始采用了CSS的方式来实现瀑布流,即通过属性column-count来控制列数,但很快发现,这样的瀑布流的顺序是从上到下后再从左到右,与原型图的要求并不符合,况且在加上懒加载后,由于整体的数据数量发生了变化,整个瀑布流相当于又重新加载了一次,不仅不能实现功能,还加大了加载的压力
所幸瀑布流还可以通过JS来进行实现,在查阅了相关的方法后,找到了符合要求的写法,具体如下:
采用左右两列布局,实时判断两侧的高度,当一侧大于另一侧时,就将对应的内容添加到少的一侧
js代码:
async isLeft(list, leftList, rightList) {let t = this;query = wx.createSelectorQuery();for (const item of list) {leftHeight <= rightHeight ? leftList.push(item) : rightList.push(item); //判断两边高度,来决定添加到那边await this.getBoxHeight(leftList, rightList);}console.log(leftList, rightList);setTimeout(() => {t.setData({show: "visible"})}, 1000)},getBoxHeight(leftList, rightList) { //获取左右两边高度return new Promise((resolve, reject) => {this.setData({leftList,rightList}, () => {query.select('#left').boundingClientRect();query.select('#right').boundingClientRect();query.exec((res) => {leftHeight = res[0].height; //获取左边列表的高度rightHeight = res[1].height; //获取右边列表的高度resolve();});});})}
wxml:
<view id="left"><view class="store_item" wx:for="{{leftList}}" wx:key="indexs" bindtap="storeIndex" data-id="{{item.id}}"><view class="store_img"><image mode="widthFix" lazy-load="true" src="" /></view><view class="store_text"><view class="text">测试用</view><view class="view"><text>浏览量:{{item.show_view}}</text></view></view></view></view><view id="right"><view class="store_item" wx:for="{{rightList}}" wx:key="indexs" bindtap="storeIndex" data-id="{{item.id}}"><view class="store_img"><image mode="widthFix" lazy-load="true" src="" /></view><view class="store_text"><view class="text">测试用</view><view class="view"><text>浏览量:{{item.show_view}}</text></view></view></view></view><view style="clear: both;"></view>
注意需要为左右两个列表设置浮动
#left{width: 49%;float: left;
}
#right{width: 49%;float: left;margin-left: 2%;
}
这样我们的瀑布流布局就算实现了
懒加载:
onReachBottom: function () {let t = thisconst start = this.data.renderedGoodsList.length; // 计算当前已渲染数据的末尾索引const end = Math.min(start + this.data.pageSize, this.data.list.length); // 计算下一批数据的结束索引const nextBatch = this.data.list.slice(start, end); // 获取下一批数据const newRenderedGoodsList = this.data.renderedGoodsList.concat(nextBatch); // 合并新数据this.isLeft(nextBatch, t.data.leftList, t.data.rightList);this.setData({renderedGoodsList: newRenderedGoodsList});},
绑定在页面最外层的scroll-view滚动事件上即可,每当滚动到底部时都会触发
<scroll-view scroll-y style="height: 100vh" bindscrolltolower="onReachBottom">
最后需要注意的是,在触发切换事件导致排序发生变化时,应当手动将左右两侧的列表的高度清空,防止重新识别高度时产生的错判导致左右换位。
希望能为你带来帮助