遇到问题时的解决方法及使用注意事项:
1、下拉刷新会导致瀑布流顺序错乱,重新new一下瀑布流即可。
2、图片宽高必须要让服务端返,前端去获取数据太多会导致性能非常慢。
3、dom加载时获取小程序的某个dom的宽度(列宽)为空,放在wx.nextTick中即可。还获取不到,就需要看自己要获取的dom是否已加载。
4、此代码抗揍,如果出问题先从自身找问题,再仔细阅读一遍此代码。
class Waterfall {
constructor(options) {
this.initWaterfall(options);
}
/**
* 初始化瀑布流
* @param {Object} options
* @param {Array<Object>} options.columns {width} - 此参数主要定义每列的宽度
*/
initWaterfall(options) {
this.columns = options.columns;
this.formatedData = [];
for (let column of options.columns) {
this.formatedData.push({
width: column.width,
height: 0
});
}
}
imageUrlFeild = 'imageUrl'
/**
* 格式化从数据中获取图片url的方法
* @param {Function | String | Number} fn - 若为函数,则需要返回瀑布流每项数据对应的图片字段
*/
formatGetImageUrlMethod(fn) {
this.imageUrlFeild = typeof fn === 'function' ? fn() : fn
}
/**
* 向瀑布流中填充数据
* @param {Object} resource - 单个瀑布流项的数据源
*/
getResourceInfo(resource) {
const _self = this
return new Promise(resolve => {
if (resource[_self.imageUrlFeild]) {
// getImageInfo方法在小程序中使用,h5中暂未测试,不过一般都是让服务端直接返回图片宽高,所以这个方法一般用不到,如果需要用到的话,必须加一层loading阻止用户操作
wx.getImageInfo({
src: resource[_self.imageUrlFeild],
success(res) {
resolve(res)
},
fail() {
resolve()
}
})
} else {
resolve()
}
})
}
/**
* 向瀑布流中补充数据
* @param {Boolean} extraVal 瀑布流的卡片中图片之外的内容
* @param {Array<resource>} resources
*/
async addResources(resources, extraVal) {
// let promiseArray = []
let newResourcesArray = Array.apply(null, Array(this.columns.length)).map(
_ => []
)
for (let resource of resources) {
// promiseArray.push(this.getResourceInfo(resource))
// let imageInfo
// imageInfo = await this.getResourceInfo(resource)
const width = Number(resource.width) || 100;
const height = Number(resource.height) || 100;
// 获取最短列的索引
const index = this.getShortestColumn();
// 卡片宽度
const imageWidth = this.formatedData[index].width;
// 附加的卡片高度在这里是写死的,每个项目会有不同高度
const extraHeight = extraVal ? extraVal : 0;
// 获取卡片高度
const cardHeight = imageWidth / (width / height) + extraHeight;
// 当前列总高度
this.formatedData[index].height += cardHeight;
// 返回卡片高度
resource.cardHeight = cardHeight;
// 返回图片高度
resource.computedHeight = cardHeight - extraVal;
// 返回当前列的数组
newResourcesArray[index].push(resource);
}
return newResourcesArray
}
/**
* 最重要的地方
* 获取当前数据中填充最短的列
* 返回最短列的索引
*/
getShortestColumn() {
let minHeight = Infinity
let minHeightColumnIndex = 0
for (let index = this.formatedData.length - 1; index > -1; index--) {
//从后往前遍历,防止每列的高度相同的情况
const height = this.formatedData[index].height
if (height <= minHeight) {
minHeightColumnIndex = index
minHeight = height
}
}
return minHeightColumnIndex
}
}
export default Waterfall;
// 例:双列瀑布流
let newList = new Waterfall({
columns: [
{
width: 列宽
},
{
width: 列宽
}
]
});
newList.addResources(lists, 卡片内除图片的额外高度).then(res => {});