最近做微信小程序涉及到了瀑布流功能,由于考虑到用户微信版本,所以放弃了官方提供的瀑布流方式(有兴趣可以访问官方文档),经过最终调研,决定使用多个数组来实现。
具体思路:以两列瀑布流为主,需要展示的数据数组为数组A,左边一列展示的为数组B,右边一列展示的为数组C,循环数组A,经过页面的渲染判断当前数据加入数组B还是数组C,比如左侧数据列表高度小于右侧,则数据进入左侧数组B,同时数据渲染,循环这一步骤直到数据渲染完毕。
具体实现:
1. 通过flex布局将页面分为两列
.container {
width: 100%;
padding: 0 24rpx; // 设置下左右边距
box-sizing: border-box;
display: flex;
align-items: flex-start; // 沿着交叉轴方向 起点 对齐
justify-content: space-between; // 两端对齐
}
<view class="container">
<view class="container-left" id="left">
<repeat for="{{leftData}}">
// ....... 瀑布流单个数据块
</repeat>
</view>
<view class="container-right" id="right">
<repeat for="{{rightData}}">
// ....... 瀑布流单个数据块
</repeat>
</view>
</view>
2. 获取element的高度
getElementSize(selector) {
return new Promise((resolve) => {
let query = wx.createSelectorQuery()
query.select(selector).boundingClientRect({
size: true
}).exec((res) => {
resolve(res)
})
})
}
3.循环原数组中的数据,分配到左右两列数组(data中定义 originData、leftData、rightData)
async splitData(){
this.setData({ // 左右两侧数组清空
leftData: [],
rightData: []
})
for (let i in this.data.originData) {
await this.setItem(this.originData[i],i) // 这里将数据原index保存了下,不需要可忽略
}
}
setItem(item, index) {
let newItem = deepClone(item) // 这里为了把原数组index保存下,深度拷贝下赋值,不需要可忽略
newItem.customIndex = index
let leftData = this.data.leftData
let rightData = this.data.rightData
return new Promise((resolve) => {
Promise.all([
this.getElementSize('#left'), // 获取左右两列的高度
this.getElementSize('#right')
]).then((res) => {
let leftElement = res[0][0]
let rightElement = res[1][0]
// 通过判断左右两列的高度来决定新的数据置入哪侧
if (leftElement.height > rightElement.height) {
leftData.push(newItem)
} else {
rightData.push(newItem)
}
this.setData({
leftData,
rightData
})
resolve(true)
})
})
},
总结:该方法就像买票的两个窗口排队情况,每次来一个人都会去人少的那一列排队,适合那种单个数据块高度不怎么变化、数据不怎么更新的情况。