微信小程序实战,基于vue2实现瀑布流
1、什么是瀑布流呢?
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。
瀑布流对于图片的展现,是高效而具有吸引力的,用户一眼扫过的快速阅读模式可以在短时间内获得更多的信息量,而瀑布流里懒加载模式又避免了用户鼠标点击的翻页操作,瀑布流的主要特性便是错落有致,定宽而不定高的设计让页面区别于传统的矩阵式图片布局模式,巧妙的利用视觉层级,视线的任意流动又缓解了视觉疲劳,同时给人以不拘一格的感觉,切中年轻一族的个性化心理。
下面这些就是用瀑布流来实现,看起来是不是很美观呢?


2、实现一个简单的瀑布流
先看一下咱们最终的试下效果吧,只是简单传入文字进行演示

1、瀑布流的特点
1、琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列。
2、唯美:图片的风格以唯美的图片为主。
3、操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前
2、核心算法
通过图片我们可以直观的看到,每一个卡片的高度都是不一样的,需要我们实时能计算高度,同时左右的高度还是不能相互影响。
这里我们主要通过两个数组进行实现,即分为左右数组,核心代码如下:
<view id="u-left-column" class="u-column">
	<slot name="left" :leftList="leftList"></slot>
</view>
<view id="u-right-column" class="u-column">
	<slot name="right" :rightList="rightList"></slot>
</view>
data() {
	return {
		leftList: [],
		rightList: [],
		tempList: [],
		scrollTop: 0,
	}
}
对传入数组进行分组和计算高度
async splitData() {
	if (!this.tempList.length) return;
	let leftRect = await this.$uGetRect('#u-left-column');
	let rightRect = await this.$uGetRect('#u-right-column');
	// 如果左边小于或等于右边,就添加到左边,否则添加到右边
	let item = this.tempList[0];
	// 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
	// 数组可能变成[],导致此item值可能为undefined
	if (!item) return;
	if (leftRect.height < rightRect.height) {
		this.leftList.push(item);
	} else if (leftRect.height > rightRect.height) {
		this.rightList.push(item);
	} else {
		// 这里是为了保证第一和第二张添加时,左右都能有内容
		// 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
		if (this.leftList.length <= this.rightList.length) {
			this.leftList.push(item);
		} else {
			this.rightList.push(item);
		}
	}
	// 移除临时列表的第一项
	this.tempList.splice(0, 1);
	// 如果临时数组还有数据,继续循环
	if (this.tempList.length) {
		this.splitData();
		return
	}
}
3、完整的组件代码如下
<template>
	<scroll-view class="scroll-y" scroll-y="true" @scrolltolower="tolower" :scroll-top="scrollTop">
		<view class="u-waterfall" id="list">
			<view id="u-left-column" class="u-column">
				<slot name="left" :leftList="leftList"></slot>
			</view>
			<view id="u-right-column" class="u-column">
				<slot name="right" :rightList="rightList"></slot>
			</view>
		</view>
	</scroll-view>
</template>
<script>
	export default {
		name: "waterfall",
		props: {
			value: {
				// 瀑布流数据
				type: Array,
				required: true,
				default: function() {
					return [];
				}
			},
			scrolltolower: {
				type: Function,
				default: () => {}
			}
		},
		data() {
			return {
				leftList: [],
				rightList: [],
				tempList: [],
				scrollTop: 0,
			}
		},
		watch: {
			copyFlowList(nVal, oVal) {
				this.tempList = this.cloneData(this.copyFlowList);
				this.splitData();
			}
		},
		mounted() {
			this.tempList = this.cloneData(this.copyFlowList);
			this.splitData();
			// this.$on('clearWaterFall', this.clear)
		},
		computed: {
			// 破坏flowList变量的引用,否则watch的结果新旧值是一样的
			copyFlowList() {
				return this.cloneData(this.value);
			}
		},
		methods: {
			async splitData() {
				if (!this.tempList.length) return;
				let leftRect = await this.$uGetRect('#u-left-column');
				let rightRect = await this.$uGetRect('#u-right-column');
				// 如果左边小于或等于右边,就添加到左边,否则添加到右边
				let item = this.tempList[0];
				// 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
				// 数组可能变成[],导致此item值可能为undefined
				if (!item) return;
				if (leftRect.height < rightRect.height) {
					this.leftList.push(item);
				} else if (leftRect.height > rightRect.height) {
					this.rightList.push(item);
				} else {
					// 这里是为了保证第一和第二张添加时,左右都能有内容
					// 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
					if (this.leftList.length <= this.rightList.length) {
						this.leftList.push(item);
					} else {
						this.rightList.push(item);
					}
				}
				// 移除临时列表的第一项
				this.tempList.splice(0, 1);
				// 如果临时数组还有数据,继续循环
				if (this.tempList.length) {
					this.splitData();
					return
				}
			},
			// 复制而不是引用对象和数组
			cloneData(data) {
				return JSON.parse(JSON.stringify(data));
			},
			tolower(e) {
				this.scrolltolower()
			},
			clear() {
				this.leftList = []
				this.rightList = []
			}
		}
	}
</script>
<style lang="scss" scoped>
	@mixin vue-flex($direction: row) {
		/* #ifndef APP-NVUE */
		display: flex;
		flex-direction: $direction;
		/* #endif */
	}
	.scroll-y {
		height: 78vh;
		margin-top: 18px;
	}
	.u-waterfall {
		@include vue-flex;
		flex-direction: row;
		align-items: flex-start;
	}
	.u-column {
		@include vue-flex;
		flex: 1;
		flex-direction: column;
		height: auto;
		width: 45vw;
		word-break: break-all;
	}
</style>
3、简单使用
基于vue的语法进行使用,先进行导入和注册
<script>
import waterfall from '../../component/waterfall/index.vue'
export default {
	name: 'content',
	components: {
		waterfall
	}
}
</script>
因为组件是基于插槽的形式进行开发的,所以我们可以直接传入咱们的样式和标签
<template>
	<view class="main">
		<waterfall :value="dataList" :scrolltolower="getRecommendLove" ref="child">
			<template v-slot:left="left">
				<view v-for="item in left.leftList" :key="item.id" class="left-content" @click="copy(item)">
					<view class="item">
						{{item.content}}
					</view>
				</view>
			</template>
			<template v-slot:right="right">
				<view v-for="item in right.rightList" :key="item.id" class="right-content" @click="copy(item)">
					<view class="item">
						{{item.content}}
					</view>
				</view>
			</template>
		</waterfall>
	</view>
</template>
最终的效果就可以达到我们的目标了

微信小程序实战,基于vue2实现瀑布流的更多相关文章
- [转]微信小程序之加载更多(分页加载)实例 —— 微信小程序实战系列(2)
		
本文转自;http://blog.csdn.net/michael_ouyang/article/details/56846185 loadmore 加载更多(分页加载) 当用户打开一个页面时,假设后 ...
 - WordPress 网站开发“微信小程序“实战(三)
		
本文是"WordPress 开发微信小程序"系列的第三篇,本文记录的是开发"DeveWork+"小程序1.2 版本的过程.建议先看完第一篇.第二篇再来阅读本文. ...
 - [转]微信小程序之购物车 —— 微信小程序实战商城系列(5)
		
本文转自:http://blog.csdn.net/michael_ouyang/article/details/70755892 续上一篇的文章:微信小程序之商品属性分类 —— 微信小程序实战商城 ...
 - [转]微信小程序之购物数量加减 —— 微信小程序实战商城系列(3)
		
本文转自:http://blog.csdn.net/michael_ouyang/article/details/70194144 我们在购买宝贝的时候,购物的数量,经常是我们需要使用的,如下所示: ...
 - 【微信小程序】转载:微信小程序实战篇-下拉刷新与加载更多
		
下拉刷新 实现下拉刷新目前能想到的有两种方式 1. 调用系统的API,系统有提供下拉刷新的API接口 当然,你可以直接在全局变量app.json的window里面配置上面这个属性,这样整个项目都允许下 ...
 - 微信小程序实战篇:商品属性联动选择(案例)
		
本期的微信小程序实战篇来做一个电商网站经常用到的-商品属性联动选择的效果,素材参考了一点点奶茶. 效果演示: 商品属性联动.gif 代码示例 1.commodity.xml <!-- < ...
 - 微信小程序实战 购物车功能
		
代码地址如下:http://www.demodashi.com/demo/12400.html 一.准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.com/ ...
 - 微信小程序实战之天气预报
		
原文:微信小程序实战之天气预报 这个案例是仿UC中天气界面做的中间也有点出入,预留了显示当前城市名字和刷新图标的位置,自己可以写下,也可以添加搜索城市.值得注意的是100%这个设置好像已经不好使了,可 ...
 - 微信小程序实战之百思不得姐精简版
		
原文:微信小程序实战之百思不得姐精简版 微信小程序基本组件和API已撸完,总归要回到正题的,花了大半天时间做了个精简版的百思不得姐,包括段子,图片,音频,视频,四个模块.这篇就带着大家简述下这个小的A ...
 - 微信小程序实战篇:基于wxcharts.js绘制移动报表
		
前言 微信小程序图表插件(wx-charts)是基于canvas绘制,体积小巧,支持图表类型饼图.线图.柱状图 .区域图等图表图形绘制,目前wx-charts是微信小程序图表插件中比较强大好使的一个. ...
 
随机推荐
- 【学习笔记】 第04章 NumPy基础:数组和矢量计算
			
前言 正式开始学习Numpy,参考用书是<用Python进行数据清洗>,计划本周五之前把本书读完,关键代码全部实现一遍 NumPy基础:数组和矢量计算 按照书中所示,要搞明白具体的性能差距 ...
 - Solutions:应用程序性能监控/管理(APM)实践---python/flask
			
本文部分内容转载自:https://blog.csdn.net/UbuntuTouch/article/details/102844900 官方文档:https://www.elastic.co/gu ...
 - 黑马程序员关于MongoDB的教程
			
基础:https://files.cnblogs.com/files/sanduzxcvbnm/mongodb_base.pdf 理解 MongoDB的业务场景.熟悉MongoDB的简介.特点和体系结 ...
 - [CG从零开始] 3. 安装 pyassimp 库加载模型文件
			
assimp 是一个开源的模型加载库,支持非常多的格式,还有许多语言的 binding,这里我们选用 assimp 的 python 的 binding 来加载模型文件.不过社区主要是在维护 assi ...
 - PHP全栈开发(八):CSS  Ⅸ dispaly & visibility
			
display用来设置一个元素如何显示: visibility用来设置一个元素可见还是隐藏. visibility:hidden: 这个语句会使元素在HTML页面中不可见.但是这个元素仍然会占用HTM ...
 - P3261 [JLOI2015]城池攻占 (左偏树+标记下传)
			
左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子 或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...
 - 2022.3.12 提高A组总结&反思
			
今天有点上头了 T1:开场秒,大水题,一眼莫队了,最后没打 T2:开场以为是费用流,后来发现费用流做不了,在做T3的时候突然发现可以状压,也没打 T3:这道题给我极大的亲切感,导致我一个上午硬钢这道题 ...
 - get,post,put,delete四种基础方法对应增删改查
			
PUT,DELETE,POST,GET四种基础方法对应增删改查 1.GET请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改.增加数 ...
 - Hudi 数据湖的插入,更新,查询,分析操作示例
			
Hudi 数据湖的插入,更新,查询,分析操作示例 作者:Grey 原文地址: 博客园:Hudi 数据湖的插入,更新,查询,分析操作示例 CSDN:Hudi 数据湖的插入,更新,查询,分析操作示例 前置 ...
 - 齐博x1标签实例:做模板组图单图无图混排的处理
			
代码如下, {qb:tag name="xxx" type="cms" rows="10"} {if ( count($rs['picurl ...