微信小程序两列瀑布流动态加载

831 阅读1分钟

个人记录用

由于涉及动态加载,所以纯css方法column-count等不太适用,需要js

两列瀑布流,每一项的宽度固定,高度不确定,每一项由两部分组成:高度不确定的图片和高度确定的内容区

思路:计算出每一项的图片的高度+固定内容高度得出项的总高,瀑布流的两列为两个list,哪个list的高度更低,就把当前项push进去,统计两个list的高度。

计算图片高度,使用img的bindload事件(如果能够从后端获取到图片的宽高可跳过此步)

<view style="display: none;" id="hidden-imgs">
      <image wx:for="{{ hiddenImgs }}" wx:key="index" data-id="{{ item.id }}" src="{{ item.imgUrl[0] }}" bindload="onImageLoad" class="hidden-img" mode="widthFix" />
</view>

获取到数据后将其单独存放在一个hiddenImgs数组中使其添加到dom而不显示,待图片加载完后会自动触发onImageLoad事件返回图片高度。

得到图片宽高为oImgW和oImgH,以iPhoneX为例,假设两列中每一项宽度为300rpx即150px


data: {
  list: [],
  listLeft: [],
  listRight: []
}

otherData: {
  itemOthersHeight: 100,  // px 列表每一项除了图片之外的元素的高度
  leftHeight: 0,	// 两列中左list的总高度
  rightHeight: 0	// 两列中右list的总高度
},

onLoad() {
  this.getList();
},

getList() {
  // ...
  this.setData({
    hiddenImgs: res.result.list,
    list: res.result.list,
    loadAll: res.result.totalCount <= 10 ? true : false
  })
},

onImageLoad(e) {
  const vm = this;
  let { listLeft, listRight, list } = vm.data;
  let { leftHeight, rightHeight, itemOthersHeight } = vm.otherData;
  const imgId = e.currentTarget.dataset.id;
  const oImgH = e.detail.height;
  const oImgW = e.detail.width;
  const realHeight = 150 * oImgH / oImgW	// 等比例计算后的图片实际展示高度

  let res = list.filter((item, index) => item.id == imgId)
  if (leftHeight <= rightHeight) {
    listLeft.push(res[0])
    vm.setData({
      listLeft: listLeft	// 两列中的左列
    })
    vm.otherData.leftHeight += realHeight + itemOthersHeight	// push之后将项的高度加给对应list的高度
  } else {
    listRight.push(res[0])
    vm.setData({
      listRight: listRight	// 两列中的右列
    })
    vm.otherData.rightHeight += realHeight + itemOthersHeight
  }
},

onReachBottom() {
  // ...
  this.setData({
    hiddenImgs: res.list,
    list: res.list
  })
}