web前端vue移动端瀑布流展示

将瀑布流抽成了vue的一个组件

<template>
  <div class="wrapper" :class="isHidden?'isHidden':''">
    <div id="sortable">
      <div class="card" v-for="item in showList">
        <div class="card_picture_warp">
        // 这里需要@load判断图片是否已加载完  由于图片加载的过慢,所以有可能在排列后,图片才显示出来,导致排列错乱
          <img class="card__picture" :src="item.thumb" alt="" @load="loadImage">
        div>
        <div class="user_info">div>
        ...
      div>
    div>
  div>
template>
<script>
  import {Indicator} from 'mint-ui';
  export default {
  //接收父组件传入的数据
    props: {
      showList: {
        type: Array,
        default: () => {
          return []
        }
      }
    },
    data() {
      return {
        isHidden: true,  //为瀑布流排列好后再进行展示 可以对用户更加友好
        isLoad: false,
        maxH: 0,
        loadNum: 0
      }
    },
    watch: {
      showList: {
        handler() {
          this.showSortable()
        }
      }
    },
    methods: {
    // isLoad 用来判断 是否所有图片都已经加载完毕
      loadImage() {
        this.loadNum++
        if (this.loadNum === this.showList.length) {
          this.isLoad = true
          this.loadNum = 0
        }
      },
      showSortable() {
        Indicator.open('加载中...');
        // 初始化状态
        this.isHidden = true
        if(this.showList.length !==0) {
        // 重置外容器的高度
          if (document.getElementsByClassName('wrapper')[0]) {
            document.getElementsByClassName('wrapper')[0].style.height = 'auto' 
          }
          const that = this
          let bbl = setInterval(function () {
            if (that.isLoad) {
      		// 进行瀑布流排序
              that.waterFall()
              // 改变容器的高度 that.maxH 在waterFall()中获取
              document.getElementsByClassName('wrapper')[0].style.height = that.maxH + 'px'
              that.isHidden = false
              that.isLoad = false
              Indicator.close();
              clearInterval(bbl)
            }
          }, 100)
        }
      },
      waterFall() {
        let box = document.getElementById('sortable');
        let items = box.children;
        // 定义每一列之间的间隙 为10像素
        let gap = 10; // 安卓一般为ios的两倍,所以需要判断
        const u = navigator.userAgent
        const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 // android终端
        const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
        if (isAndroid) {
          gap = 10
        } else if (isiOS) {
          gap = 20
        }
        let itemWidth = items[0].offsetWidth;
        let leftWidth = items[0].offsetWidth * 2 * 0.03
        // 1- 确定列数
        let columns = 2;
        let arr = [];
        for (let i = 0; i < items.length; i++) {
          if (i < columns) {
            // 2- 确定第一行
            items[i].style.top = 2 + 'vw';
            items[i].style.left = (itemWidth + gap) * i + leftWidth + 'px';
            arr.push(items[i].offsetHeight);
          } else {
            // 其他行
            // 3- 找到数组中最小高度  和 它的索引
            let minHeight = arr[0];
            let index = 0;
            for (let j in arr) {
              if (minHeight > arr[j]) {
                minHeight = arr[j];
                index = j;
              }
            }
            // 4- 设置下一行的第一个盒子位置
            // top值就是最小列的高度 + gap
            items[i].style.top = arr[index] + gap + 20 + 'px';
            // left值就是最小列距离左边的距离
            items[i].style.left = items[index].offsetLeft + 'px';

            // 5- 修改最小列的高度
            // 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 间隙的高度
            arr[index] = arr[index] + items[i].offsetHeight + gap;
            // 获取整个容器的整体高度
            this.maxH = arr[index]
          }
        }
      }
    }
  }
</script>

你可能感兴趣的:(web前端vue移动端瀑布流展示)