移动端瀑布流加上拉加载

效果图:

image.png

实现思路:

核心是vue的nextTick配合vant中的list上拉加载组件实现;
这是两列,所以这里用了两个容器,也就是两个数组,一列为一个容器,然后往里push数据,在判断哪一个容器的高度小,就往哪一列push数据,页面初始化的时候,左侧容器的高度最低,然后往里添加了一条数据,这里就碰到了一个问题,由于实现逻辑是判断页面元素高度,第一次渲染完后,该怎么再次执行判断函数呢,这里就用到了vue的nextTike,页面渲染完后,就会触发此函数; this.nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上;

代码


<template>
  <div>
    <van-list
      v-model="loading"
      v-bind="$attrs"
      @load="onLoad"
    >
      <div
        class="waterfall-wrapper"
      >
        <ul
          ref="leftWaterfall"
          class="left-waterfall"
        >
          <li
            v-for="(item,index) in leftItems"
            :key="index"
          >
            <div
              class="img-card"
            >
              <van-image
                width="100%"
                :src="item.img"
                fit="fill"
              />
      
              <div class="topping-tab">
                置顶
              </div>
              <div class="right-btn">
                发送
              </div>

              <p class="text-ellipsis img-card-name">
                图片名称图片名称图{{ index }}
              </p>
            </div>
          </li>
        </ul>
        <ul
          ref="rightWaterfall"
          class="right-waterfall"
        >
          <li
            v-for="(item,index) in rightItems"
            :key="index"
          >
            <div
              class="img-card"
            >
              <van-image
                width="100%"
                :src="item.img"
                fit="fill"
              />
   
              <div class="topping-tab">
                置顶
              </div>
              <div class="right-btn">
                发送
              </div>

              <p class="text-ellipsis img-card-name">
                图片名称图片名称图{{ index }}
              </p>
            </div>
          </li>
        </ul>
      </div>
    </van-list>
  </div>
</template>

<script>
export default {
  props: {
    imgCardList: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data () {
    return {
      loading: false,
      list: [],
      leftItems: [],
      rightItems: [],
      imgCardListS: [],
      waterfallFlage: false,
      waterfalNum: 0
    }
  },
  computed: {
  },
  created () {
  },
  mounted () {

  },
  methods: {
    onLoad () {
      this.$emit('onLoad')
    },
    updateWaterfall () {
      const leftHeight = this.$refs.leftWaterfall.clientHeight
      const rightHeight = this.$refs.rightWaterfall.clientHeight
      if (this.waterfalNum !== this.imgCardList.length) {
        this.waterfallFlage = false
      }
      if (!this.waterfallFlage) {
        this.waterfallFlage = true
        if (this.imgCardList.length !== 0) {
          this.imgCardListS = this.$deepClone(this.imgCardList)
          this.imgCardListS.splice(0, this.waterfalNum)
          this.waterfalNum = this.imgCardList.length
        } else {
          this.imgCardListS = this.$deepClone(this.imgCardList)
          this.waterfalNum = this.imgCardList.length
        }
      }
      const item = this.imgCardListS.shift()
      if (item == null) {
        return
      }
      if (leftHeight <= rightHeight) {
        this.leftItems.push(item)
      } else {
        this.rightItems.push(item)
      }
      this.$nextTick(() => {
        this.updateWaterfall()
      })
    }
  }
}
</script>

<style lang="scss" >
.waterfall-wrapper{
  overflow: hidden;
  ul{
    width: 48%;
  }
  li{
    width: 100%;
    div{
      width: 100%;
      img{
        width: 100%;
        display: block;
        min-height: 86px;
        border-radius: 8px;
      }
    }
  }
  .left-waterfall{
    float: left;
  }
  .right-waterfall {
    float: right;
  }
}

.box>div{
    width: 99%;
    margin-bottom: 20px;
}
.img-card{
  position: relative;
  font-size: 14px;
  margin-bottom: 15px;
  border-radius:  8px;
  overflow: hidden;
  .topping-tab{
    position: absolute;
    top: 8px;
    left: 8px;
    width: 40px;
    height: 22px;
    background:rgba(0, 0, 0, 0.6);
    border-radius: 4px;
    font-size: 12px;
    font-weight: 400;
    color: #FFFFFF;
    text-align: center;
    line-height: 22px;
  }
  .right-btn{
    width: 66px;
    height: 28px;
    position: absolute;
    top: 8px;
    right: 8px;
    text-align: center;
    line-height: 28px;
    background: #006EF3;
    border-radius: 14px;
    font-weight: 400;
    color: #FFFFFF;
    line-height: 28px;
  }
  .img-card-name{
    padding: 10px 8px;
    position: absolute;
    bottom: 0px;
    color: #FFFFFF;
    box-sizing: border-box;
    margin: 0;
    width: 100%;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
  }
}
</style>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容