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;
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的瀑布流组件-使用说明的更多相关文章
- vuejs和webpack项目(VueComponent)初尝试——瀑布流组件
碎碎念: 好久不见,最近自己有些懈怠没更过多少博,主要原因之一是对自己学习方式的一些思考,翻看之前的博客多是记录学习笔记这反映出了自己对于前端还停留在学习-复习知识点的阶段压根没多少实践经验啊 ...
- 自己实现vue瀑布流组件,含详细注释
我知道vue有瀑布流插件vue-waterfall-easy,但是使用的时候与我的预期有部分别,所以就自己动手写了这个组件 人和动物的根本区别是是否会使用工具,我们不仅要会使用,还要会创造工具,别人提 ...
- Vue2.0表单校验组件vee-validate的使用
vee-validate使用教程 *本文适合有一定Vue2.0基础的同学参考,根据项目的实际情况来使用,关于Vue的使用不做多余解释.本人也是一边学习一边使用,如果错误之处敬请批评指出* 一.安装 n ...
- Vue2.0的变化 ,组件模板,生命周期,循环,自定义键盘指令,过滤器
组件模板: 之前: <template> <h3>我是组件</h3><strong>我是加粗标签</strong> </templat ...
- Webpack+vue2.0如何注册全局组件 (01)
Part 1, 问题: webpack + vue2.0框架中,如何在入口js中注册组件? 就是在一个月以前,匆匆闯入vuejs这个社群,基本了解了vuejs的一些基础特性和语法.笔者兴致勃勃地开始想 ...
- Vue2.0中的transition组件
组件的过度 Vue1.0中transition做为标签的行内属性被vue支持.但在Vue2.0中.Vue放弃了旧属性的支持并提供了transition组件,transition做为标签被使用. 使用t ...
- Vue2.0如何实现父组件与子组件之间的事件发射与接收
关于vue2.0的事件发射和接收,大家都知道$dispatch和$broadcast在vue2.0已经被弃用了,取而代之的是更加方便快捷的方式,使用事件中心,组件通过它来互相通信,不管组件在哪一个层都 ...
- 在vue2.0中引用element-ui组件库
element-ui是由饿了么团队开发的一套基于 Vue 2.0 的桌面端组件库. 官网:http://element.eleme.io/ 安装 npm i element-ui -S 引用完整的el ...
- 基于vue2.0的一个分页组件
分页组件在项目中经常要用到之前一直都是在网上找些jq的控件来用(逃..),最近几个项目用上vue了项目又刚好需要一个分页的功能.于是百度发现几篇文章介绍的实在方式有点复杂, 没耐心看自己动手造轮子写了 ...
随机推荐
- 责任链模式(Chain of Responsibility)
责任链模式(Chain of Responsibility)接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求 ...
- 外观模式(Facade)
外观模式(Facade) 外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合 ...
- 分布式版本控制系统 Git 教程
简介 Git 是什么? Git 是一个开源的分布式版本控制系统. 什么是版本控制? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 什么是分布式版本控制系统? 介绍分布 ...
- Python 串口通信操作
下载 pyserial包 https://pypi.python.org/packages/source/p/pyserial/pyserial-2.7.tar.gz#md5=794506184df ...
- SQL面试题:有A B C三列,用SQL语句实现:当A列大于B列时选择A列否则选择B列
.请教一个面试中遇到的SQL语句的查询问题 表中有A B C三列,用SQL语句实现:当A列大于B列时选择A列否则选择B列,当B列大于C列时选择B列否则选择C列. ------------------- ...
- PHP数组实际占用内存大小的分析
一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G.下面我们可以粗略的估算PHP数组占用内存的大小,首先我们测试1000个元素的整数 ...
- SQL Server插入数据和删除数据
首先在我的Student表中插入几条数据,由于我的表已经创建完成了,所以就没有创建表的 sql 语句了,不过可以看我的上一篇文章: http://www.cnblogs.com/Brambling/p ...
- extjs 关于dom操作的几个库
经过几天的学习研究,发现ext与jquery的设计思路完全是来自两个方向. jquery是内聚,把所有东西都放在$的下面,而ext是采用分模块的设计思路,每个功能封装一个库.这样就形成了各自的实用风格 ...
- dynamic programming 学习
这是看到一位大神,写的关于dynamic programming的博客,认为很好.简单分析下.然后给出链接. 背景问题就是 有一个国家,全部的国民都很老实憨厚,某天他们在自己的国家发现了十座金矿.而且 ...
- 剑指Offer面试题39(Java版):二叉树的深度
题目:输入一棵二叉树的根节点,求该数的深度. 从根节点到叶结点依次进过的结点(含根,叶结点)形成树的一条路径,最长路径的长度为树的深度. 比如.例如以下图的二叉树的深度为4.由于它从根节点到叶结点的最 ...