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

使用瀑布流布局组件: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;
width: 100%; // 移动端生效
.img-box {
display: inline-block;
width: 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 {
width: 100%;
background: yellow;
}
img {
width: 100%;
vertical-align: bottom;
}
.img-info {
background: #fff;
// padding: .6em;
}
}
}
.loading {
text-align: center;
width: 100%;
position: fixed;
bottom: 10px;
left: 50%;
margin-left: -15px;
width: 30px;
height: 30px;
}
.loading.first-loading {
// 首次预加载白屏,让加载动画处于中间
top: 50%;
margin-top: -15px;
}
.double-bounce1,
.double-bounce2 {
width: 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? '':{width: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',width: isMobile ? '' : colWidth+'px'}"
)
.img-inner-box
//- div.img-wraper(:style="{width:imgWidthC+'px',height:v.height?v.height+'px':''}")
a.img-wraper(
:style="{width:'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>

vue2.0的瀑布流组件-使用说明的更多相关文章

  1. vuejs和webpack项目(VueComponent)初尝试——瀑布流组件

    碎碎念:     好久不见,最近自己有些懈怠没更过多少博,主要原因之一是对自己学习方式的一些思考,翻看之前的博客多是记录学习笔记这反映出了自己对于前端还停留在学习-复习知识点的阶段压根没多少实践经验啊 ...

  2. 自己实现vue瀑布流组件,含详细注释

    我知道vue有瀑布流插件vue-waterfall-easy,但是使用的时候与我的预期有部分别,所以就自己动手写了这个组件 人和动物的根本区别是是否会使用工具,我们不仅要会使用,还要会创造工具,别人提 ...

  3. Vue2.0表单校验组件vee-validate的使用

    vee-validate使用教程 *本文适合有一定Vue2.0基础的同学参考,根据项目的实际情况来使用,关于Vue的使用不做多余解释.本人也是一边学习一边使用,如果错误之处敬请批评指出* 一.安装 n ...

  4. Vue2.0的变化 ,组件模板,生命周期,循环,自定义键盘指令,过滤器

    组件模板: 之前: <template> <h3>我是组件</h3><strong>我是加粗标签</strong> </templat ...

  5. Webpack+vue2.0如何注册全局组件 (01)

    Part 1, 问题: webpack + vue2.0框架中,如何在入口js中注册组件? 就是在一个月以前,匆匆闯入vuejs这个社群,基本了解了vuejs的一些基础特性和语法.笔者兴致勃勃地开始想 ...

  6. Vue2.0中的transition组件

    组件的过度 Vue1.0中transition做为标签的行内属性被vue支持.但在Vue2.0中.Vue放弃了旧属性的支持并提供了transition组件,transition做为标签被使用. 使用t ...

  7. Vue2.0如何实现父组件与子组件之间的事件发射与接收

    关于vue2.0的事件发射和接收,大家都知道$dispatch和$broadcast在vue2.0已经被弃用了,取而代之的是更加方便快捷的方式,使用事件中心,组件通过它来互相通信,不管组件在哪一个层都 ...

  8. 在vue2.0中引用element-ui组件库

    element-ui是由饿了么团队开发的一套基于 Vue 2.0 的桌面端组件库. 官网:http://element.eleme.io/ 安装 npm i element-ui -S 引用完整的el ...

  9. 基于vue2.0的一个分页组件

    分页组件在项目中经常要用到之前一直都是在网上找些jq的控件来用(逃..),最近几个项目用上vue了项目又刚好需要一个分页的功能.于是百度发现几篇文章介绍的实在方式有点复杂, 没耐心看自己动手造轮子写了 ...

随机推荐

  1. 一个for循环打印二维数组

    #include<stdio.h> #define MAXX 2 #define MAXY 3 void printarray() { ,,,,,}; ;i< MAXX*MAXY;i ...

  2. js中一些注意点 ps不断更新中....

    nextSibling 和 nextElementSibling 的区别 (previousSibling 和 previousElementSibling ) nextSibling 在IE8及以下 ...

  3. 自动化运维工具——ansible详解(二)

    Ansible playbook 简介 playbook 是 ansible 用于配置,部署,和管理被控节点的剧本. 通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机 ...

  4. git操作之上传gitthub

    push 失败解决方法: 分支操作: 分支操作之覆盖: 主master操作:

  5. 守护进程VS守护线程

    守护(daemon)进程 引入: join()方法可以使一个进程运行完之后再执行下一个进程,而daemon()方法就是主进程的代码执行完毕之后,不需要等待子进程,立即终止子进程. join()方法和d ...

  6. (四):C++分布式实时应用框架——状态中心模块

    C++分布式实时应用框架--状态中心模块 上篇:(三):C++分布式实时应用框架--系统管理模块 技术交流合作QQ群:436466587 欢迎讨论交流 版权声明:本文版权及所用技术归属smartguy ...

  7. 1.5 sleep()方法

    方法sleep()的作用是在指定的毫秒数内让当前"正在执行的线程"休眠(暂停执行).这个"正在执行的线程"是指this.currentThread()返回的线程 ...

  8. django模板语法之include

    假如我们有以下模板index.html,代码为: <!DOCTYPE html> <html lang="en"> <head> <met ...

  9. HDU_1698 Just a Hook(线段树+lazy标记)

    pid=1698">题目请点我 题解: 接触到的第一到区间更新,须要用到lazy标记.典型的区间着色问题. lazy标记详情请參考博客:http://ju.outofmemory.cn ...

  10. 基于C++11的线程池

    1.封装的线程对象 class task : public std::tr1::enable_shared_from_this<task> { public: task():exit_(f ...