zoukankan      html  css  js  c++  java
  • vue2.0的瀑布流组件-使用说明

    做一个小项目,需要瀑布流,就选他了,先看看效果

    使用瀑布流布局组件:vue-waterfall-easy
        下载引入:
            方式一:直接从git上复制组件的完整代码,引入vue组件文件即可
                import vueWaterfallEasy from '你的路径/组件名.vue'
                
            方式二:通过npm全局安装:cnpm install vue-waterfall-easy --save-dev
                import vueWaterfallEasy from 'vue-waterfall-easy'
            
            报错注意: 
                Cannot find module 'pug'   原因是:没有安装pug模块,安装:cnpm install --save pug        或去除:lang='pug'
                sass-loader没安装:        解决:安装sass或修改sass为less
    
        注册:
            要在当前组件中注册该组件:export default { components:{vueWaterfallEasy}}

    组件的使用:

    <template>
      <div id="all_user">
        <div class="search_box">
          <input type="text" placeholder="请输入编号或名称"><button><i class="tt tt-quanburen"></i>搜索</button>
        </div>
    
        <vueWaterfallEasy :imgsArr="imgsArr" @scrollLoadImg="fetchImgsData">
          <template slot-scope="props">
            <div class="player_info">
                <div class="title"><i class="tt tt-quanburen"></i>{{props.value.info}}</div>
                <div class="ticket">
                  <mt-button @click="upLoadTicket(props.value.id)" size="small"><i class="tt tt-quanburen"></i>投票</mt-button>
                </div>
                <p class="num">{{props.index+1}}票</p>
              </div>
          </template>
        </vueWaterfallEasy>
      </div>
    </template>
    
    <script>
    import vueWaterfallEasy from './Waterfall/vue-waterfall-easy.vue'
    
    export default {
      name: 'app',
      data() {
        return {
          imgsArr: [],
          fetchImgsArr: []
        }
      },
      components: {
        vueWaterfallEasy
      },
      methods: {
        // 假数据
        initImgsArr(n, m) { //num 图片数量
          var arr = []
          for (var i = n; i < m; i++) {
            arr.push({ id:i,src: `./src/assets/images_test/${i + 1}.jpg`, link: 'https://www.baidu.com', info: '一些图片描述文字' })
          }
          return arr
        },
    
        fetchImgsData() {
          this.imgsArr = this.imgsArr.concat(this.fetchImgsArr)
        },
    
        upLoadTicket(index){ //投票按钮
          console.log(index);
        }
      },
      created() {
        this.imgsArr = this.initImgsArr(0, 5)
        this.fetchImgsArr = this.initImgsArr(5, 10) // 模拟每次请求的新的图片的数据数据
      },
    
    }
    
    </script>

    vue-waterfall-easy.vue组件

    <!-- —————————————↓SCSS———————分界线————————————————————————— -->
    <style lang="less">
    .vue-waterfall-easy {
      position: relative;
       100%; // 移动端生效
      .img-box {
        display: inline-block;
         50%; // 移动端生效
        box-sizing: border-box;
        float: left; // 首行排版
        transition: left 1s, top 1s;
    
        .img-inner-box {
          box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
          .img-wraper {
             100%;
            background: yellow;
          }
          img {
             100%;
            vertical-align: bottom;
          }
          .img-info {
            background: #fff;
            // padding: .6em;
          }
        }
      }
      .loading {
        text-align: center;
         100%;
        position: fixed;
        bottom: 10px;
        left: 50%;
        margin-left: -15px;
         30px;
        height: 30px;
      }
      .loading.first-loading {
        //  首次预加载白屏,让加载动画处于中间
        top: 50%;
        margin-top: -15px;
      }
      .double-bounce1,
      .double-bounce2 {
         100%;
        height: 100%;
        border-radius: 50%;
        background-color: #67CF22;
        opacity: 0.6;
        position: absolute;
        top: 0;
        left: 0;
    
        animation: bounce 2.0s infinite ease-in-out;
      }
    
      .double-bounce2 {
        animation-delay: -1.0s;
      }
    
    
    
      @keyframes bounce {
        0%,
        100% {
          transform: scale(0.0);
        }
        50% {
          transform: scale(1.0);
        }
      }
    }
    </style>
    
    <!-- —————————————↓HTML————————分界线———————————————————————— -->
    <template lang="pug">
    .vue-waterfall-easy(
      :style="isMobile? '':{colWidth*columnCount+'px',left:'50%',marginLeft: -1*colWidth*columnCount/2 +'px'}"
    )
      div.img-box(
        v-for="(v,i) in imgsArrC",
        :style="{padding:gap/2+'px', isMobile ? '' : colWidth+'px'}"
      )
        .img-inner-box
          //- div.img-wraper(:style="{imgWidthC+'px',height:v.height?v.height+'px':''}")
          a.img-wraper(
            :style="{'100%',height:v.height?'auto':''}"
            :href="v.link"
          )
            img(:src="v.src")
          div.img-info
            slot(:index="i",:value="v")
    
      .loading(v-if="isPreloadingC",:class="{'first-loading':isFirstTIme}")
        div.double-bounce1
        div.double-bounce2
    
    
    </template>
    
    <!-- ——————————————↓JS—————————分界线———————————————————————— -->
    <script>
    //import XXX from './components/XXX'
    
    export default {
      name: 'vue-waterfall-easy',
      //组件参数
      props: {    
        gap: {    //图片间隔
          type: Number, 
          default: 10
        },
        maxCols: {    //最大的列数
          type: Number,
          default: 5
        },
        imgsArr: {    //请求返回的图片数据
          type: Array,
          required: true
        },
        imgWidth: {   //制定图片的同一宽度
          type: Number,
          default: 240
        },
        timeOut: { // 预加载事件小于500毫秒就不显示加载动画,增加用户体验
          type: Number,
          default: 500
        }
      },
      data() {
        return {
          msg: 'this is from vue-waterfall-easy.vue',
          columnCount: NaN, // 列数,根据窗口大小初始化
          isMobile: navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i), // 初始化移动端
          beginIndex: NaN, // 第二列首张图片的index,从这一张开始重新计算图片位置
    
          colsHeightArr: [], // 每一列的图片总和高度为元素组成的数组
          imgBoxEls: null, // 所有的.img-box元素
          isPreloading: true, // 预加载状态中(1.以等待图片替换 2.图片全部预加载完显示)
          isPreloadingC: true,
          imgsArrC: [], // 预加载完之后再才开始
          loadedCount: 0, // 已经加载图片数量
          isFirstTIme: true, // 首次加载
        }
      },
      computed: {
        colWidth() { // 每一列的宽度
          return this.imgWidth + this.gap
        },
        imgWidthC() { // 对于移动端重新计算图片宽度
          return this.isMobile ? window.innerWidth / 2 - this.gap*2 : this.imgWidth
        }
      },
      methods: {
        waterfall() { // 执行瀑布布局
          for (var i = this.beginIndex; i < this.imgsArr.length; i++) {
            var minHeight = Math.min.apply(null, this.colsHeightArr) // 最低高低
            var minIndex = this.colsHeightArr.indexOf(minHeight) // 最低高度的索引
            var width = this.imgBoxEls[0].offsetWidth // 图片的宽度获取
            // 设置元素定位的位置
            this.imgBoxEls[i].style.position = 'absolute'
            this.imgBoxEls[i].style.left = minIndex * width + 'px'
            this.imgBoxEls[i].style.top = minHeight + 'px'
    
            // 更新colsHeightArr
            this.$set(this.colsHeightArr, minIndex, minHeight + this.imgBoxEls[i].offsetHeight)
          }
          this.beginIndex = this.imgsArr.length
        },
    
        loadFn(e, oImg, i) { // 每张图片预加载完成执行函数
          this.loadedCount++
          if (e.type === 'load') { // 使用图片原始宽度计算图片的高度
            this.$set(this.imgsArr[i], 'height', Math.round(this.imgWidthC / (oImg.width / oImg.height)))
          }
          if (this.loadedCount === this.imgsArr.length) {
            this.imgsArrC = this.imgsArr.concat([])
    
    
            this.isPreloading = false
            this.isFirstTIme = false
    
            // 预加载完毕
            this.$nextTick(() => {
              this.initImgBoxEls()
              this.$emit('preloaded')
    
            })
          }
        },
        preload() {
          this.imgsArr.forEach((v, i) => {
            if (i < this.loadedCount) return
    
            var oImg = new Image()
            oImg.addEventListener('load', (e) => {
              this.loadFn(e, oImg, i)
            })
            oImg.src = v.src
          })
        },
    
    
        // -----------------初始化化------------------------
    
        initColsHeightArr() { // 第一行元素的高度组成的数组-初始化
          this.colsHeightArr = [] // 列数发生变化重新初始化
          for (var i = 0; i < this.columnCount; i++) {
            this.imgBoxEls[i].style.position = 'static' // 重置下position
            var height = this.imgBoxEls[i].offsetHeight
            this.colsHeightArr.push(height)
          }
        },
        initImgBoxEls() { // 初始化所有装图片的元素集合,注意高度获取需要在图片加载完成之后,所以在window.onload 事件中初始化
          this.imgBoxEls = document.getElementsByClassName('img-box')
        },
    
        initColumnCount() { // 列数初始化
    
          var winWidth = window.innerWidth
          var columnCount = parseInt(winWidth / this.colWidth)
          columnCount = columnCount === 0 ? 1 : columnCount
          this.columnCount = this.isMobile
            ? 2
            : (columnCount > this.maxCols ? this.maxCols : columnCount)
    
        },
      },
      mounted() {
        // ==1== 根据窗口大小初始化列数
        this.initColumnCount()
        this.beginIndex = this.columnCount // 开始排列的元素索引
    
        // ==2== 根据预加载完成的图片的长宽比,计算图片的高度
        this.preload()
    
        this.$on('preloaded', () => {
          if (this.colsHeightArr.length === 0) this.initColsHeightArr() // 第一次初始化
          this.waterfall()
        })
    
        window.addEventListener('resize', () => {
          var old = this.columnCount
          this.initColumnCount()
          if (old === this.columnCount) return // 列数不变直接退出
          this.beginIndex = this.columnCount // 开始排列的元素索引
    
          this.initColsHeightArr()
          this.waterfall()
    
    
        })
          // console.log(this.$el.parentNode)
          // console.log(this.$el.parentNode, this.$el.parentNode.scrollTop + this.$el.parentNode.offsetHeight, this.$el.parentNode.scrollHeight)
    
        this.$el.parentNode.addEventListener('scroll', () => {
          if (this.isPreloading) return
          const lastImgHeight = this.imgsArr[this.imgsArr.length - 1].height
          // console.log(this.$el.parentNode, this.$el.parentNode.scrollTop + this.$el.parentNode.offsetHeight, this.$el.parentNode.scrollHeight)
          
          if (this.$el.parentNode.scrollTop + this.$el.parentNode.offsetHeight > this.$el.parentNode.scrollHeight - lastImgHeight) {
            this.$emit('scrollLoadImg')
            console.log('加载');
          }
        })
    
      },
      watch: {
        imgsArr(newV, oldV) {
          if (newV.length === oldV.length) return
          this.isPreloading = true // 预加载新的图片资源
          this.preload()
    
          // setTimeout(()=>{ // 模拟图片预加载时间为1s
    
          // this.preload()
          // },1000)
    
        },
        isPreloading(v) {
          if (v) {
            setTimeout(() => {
              if (!this.isPreloading) return // 500毫秒内预加载完图片则不显示加载动画
              this.isPreloadingC = true
            }, this.timeOut)
          } else {
            this.isPreloadingC = false
          }
    
        }
      }
    }
    </script>
  • 相关阅读:
    【原创】Apache ab结果参数详解
    【转载】QPS,用户平均等待时间,服务器平均请求处理时间
    【原创】Apache ab测试时出现:apr_socket_recv "connection reset by peer" 104
    【做题】Codeforces Round #429 (Div. 2) E. On the Bench——组合问题+dp
    oracle递归查询
    http1.0和1.1的区别
    here with you
    spring杂碎
    西海情歌
    //随机生成 10到20条数据 数据包含 用户名(5-10位的字母) 性别 年龄(1-100岁)
  • 原文地址:https://www.cnblogs.com/LChenglong/p/8073332.html
Copyright © 2011-2022 走看看