问题
小程序开发受到一些限制,故使用H5和APP的开发思路容易出现问题,做毕业设计需要用到瀑布流布局,看了网上的方法主要有以下三种,但基本都存在问题。
1、使用纯css样式排列出瀑布流布局
核心代码:
- 父元素:column-count: 2
- 子元素:break-inside: avoid
局限:只能一次性展示全部数据,不能做动态数据加载,数据显示位置会随数据加载而错位。
案例
https://blog.csdn.net/yuf0812/article/details/80255921
见第一条
2、分成左右两列 根据单条数据索引的奇偶排列出瀑布流布局
核心代码:
- wx-if="{{index%2==0}}"
局限:当奇数列的元素高度大于或小于偶数列的元素高度时,数据累计过多时会出现较大的高度差,容易出现只有一侧显示数据的情况。
案例
https://blog.csdn.net/yuf0812/article/details/80255921
见第二条
3、分成左右两列 根据图片高度排列出瀑布流布局
核心代码:
- 略(获取图片高度,依次累计排列)
局限:适用于近有图片或者文字高度固定的情况,当文字高度不固定,数据累积到一定程度时也会出现错位的情况。
注:在仅展示图片或展示文字叠在在图片上时力推该方法。
案例
点击此处查看案例
新方法
利用节点选择器计算出左右栏整体高度,依次插入数据。
适用范围:任何场景均可完美使用。
缺点:对性能有要求,不建议单次加载数据超过20条。
上效果
ewe
html
<view class="left">
<block wx:for="{{leftList}}" wx:key="index">
<view class="box" style="background:{{item[0]}};height:{{item[1]*2}}rpx">
{{item[2]}}
</view>
</block>
</view>
<view class="right">
<block wx:for="{{rightList}}" wx:key="index">
<view class="box" style="background:{{item[0]}};height:{{item[1]*2}}rpx">
{{item[2]}}
</view>
</block>
</view>
css
.left, .right {
width: 340rpx;
margin-left: 24rpx;
float: left;
/* background: greenyellow; */
}
/* .right{
background: palevioletred;
} */
.box {
margin-bottom: 24rpx;
border-radius: 20rpx;
color: #fff;
font-size: 70px;
display: flex;
justify-content: center;
align-items: center;
}
js
Page({
//页面的初始数据
data: {
total: [], //全部数据
leftList: [], //左侧数据
rightList: [], //右侧数据
},
// 生命周期函数--监听页面加载
onLoad: function(options) {
this.data.total = this.getArr(500) //生成并返回500条数据
this.getData() //调用加载数据函数
},
// 页面上拉触底事件的处理函数
onReachBottom: function() {
if (this.data.leftList.length + this.data.rightList.length == this.data.total.length) { //左侧已显示数据 + 右侧已显示数据 == 已生成的所有数据
wx.showToast({
title: '已加载完闭' //提示数据加载完毕
})
} else {
wx.showLoading({
title: '加载数据' //提示加载数据
})
setTimeout(() => {
wx.hideLoading() //隐藏加载框
this.getData() //调用加载数据函数
}, 800)
}
},
// 生成数据数组 参数Len 返回 [[color, height, index],[...],[...]]
getArr(Len) {
// 生成单条数据
function getData() {
let color = new String() //随机颜色
for (let i = 0; i < 6; i++) {
color += (Math.floor(Math.random() * 16)).toString(16)
} //生成6位随机16进制数字
let num = Math.floor(Math.random() * 150 + 150) //生成随机高度
return ['#' + color, num] //返回[color, height]
}
// 生成数据数组
let arr = new Array()
for (let i = 0; i < Len; i++) {
arr.push(getData().concat(i))
}
return arr
},
// 加载数据
getData() {
let len = this.data.leftList.length + this.data.rightList.length //获取已显示数组长度
let con = this.data.total.slice(len, len + 20) //获取添加20条数组数据
let leftData = this.data.leftList
let rightData = this.data.rightList
function selector(Class) { //Promise封装节点查询方法
return new Promise(resolve => {
wx.createSelectorQuery().select(Class)
.boundingClientRect(res => {
resolve(res.height)
}).exec()
})
}
let _this = this
async function example() {
let listHeight = [] //定义一个数组 存放左右两侧高度
for (let i = 0; i < con.length; i++) { //遍历瀑布流元素
await selector('.left').then(res => {
listHeight[0] = res
})
await selector('.right').then(res => {
listHeight[1] = res
})
console.log('左右高度', listHeight)
if (listHeight[0] > listHeight[1]) { //根据左右高度判断渲染至哪一列
rightData.push(con[i])
} else {
leftData.push(con[i])
}
_this.setData({ //注意:使用的是this.setData 不建议单次加载超过20条
leftList: leftData,
rightList: rightData
})
}
}
example()
}
})
有用支持一下吧