Vue3实现简单的瀑布流效果,可抽离成组件直接使用

先来看下效果图

瀑布流中的内容可进行自定义,这里的示例图是通过不同背景颜色的展示进行区分,每个瀑布流中添加了自定义图片和文字描述。

实现方式:

1.建立子组件(可单独抽离)写出瀑布流的样式

文件名为waterFall.vue

复制代码
<template>
	<div class="list">
		<div
			class="item"
			v-for="(item, index) in waterList"
			:style="{
				width: width + 'px',
				height: item.height + 'px',
				left: item.left + 'px',
				top: item.top + 'px',
				background: item.background,
			}"
		>
			<img :src="item.image" :alt="item.text" />
			<p class="text-box">{{ item.text }}</p>
		</div>
	</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
const props = defineProps({
	list: {
		type: Array,
		default: () => {
			return [];
		},
	},
});

// 图片宽度
const width = 120;
// 图片上下间距
const gap = 20;
// 瀑布流数组
const waterList = ref([]);
// 列高度数组
const heightList = reactive([]);

// 屏幕宽度需要在 mounted 之后拿到
onMounted(() => {
	// 计算列数
	const column = Math.floor(document.body.clientWidth / width);
	// 核心内容就是维护每个图片的 left、top
	for (let i = 0; i < props.list.length; i++) {
		// 先铺上第一行(i < column 则表示是第一行)
		if (i < column) {
			props.list[i].top = 0;
			props.list[i].left = width * i;
			// 塞进瀑布流
			waterList.value?.push(props.list[i]);
			// 高度数据更新
			heightList[i] = props.list[i].height;
		}

		// 后面的就要一张张塞进去,每次找出最低的列往里塞
		else {
			// 最低的高度,先默认为第一列高度
			let current = heightList[0];
			// 最低的列,先默认为第一个
			let col = 0;

			// 循环每一列进行比较
			heightList.forEach((h, i) => {
				if (h < current) {
					current = h;
					col = i;
				}
			});
			console.log('最低的列', col, '高度为', current);

			// 由此计算出该图片的 left、top
			props.list[i].left = col * width;
			props.list[i].top = current + gap;
			// 塞进瀑布流
			waterList.value.push(props.list[i]);

			// 更新列高度数组
			heightList[col] = current + gap + props.list[i].height;
		}
	}
	console.log('waterList', waterList.value);
	console.log('heightList', heightList);
});
</script>
<style lang="scss" scoped>
.list {
	position: relative;
	height: 100%;
	overflow-y: auto;
	width: 100%;
	.item {
		position: absolute;
		.text-box {
			font-weight: 500px;
			font-size: 18px;
			color: #000000;
		}
	}
}
</style>

2.在父组件中引入使用

父组件中引入使用,其中list为展示的瀑布流数组,class可设置当前瀑布流的一些盒子样式

复制代码
<water-fall :list="list" class="water-fall" />

3.在父组件中传值实现瀑布流效果

在父组件中设置瀑布流的数据,这里为了方便展示,直接使用的样例数据,实际开发中,可根据接口来进行获取。

其中的height是指瀑布流中每一个的高度,background为背景颜色,image为自定义的图片,text为描述,以上均可根据个人需求进行自定义展示。

复制代码
const list = [
	{
		height: 300,
		background: 'red',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 400,
		background: 'pink',
		text: '美术作品+沈佳宜',
		image: '/images/works-publicity/tradition.png',
	},
	{
		height: 500,
		background: 'blue',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 200,
		background: 'green',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 300,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 400,
		background: '#CC00FF',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 200,
		background: 'pink',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 100,
		background: '#996666',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 300,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 400,
		background: '#CC00FF',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 200,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 100,
		background: '#996666',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 300,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 400,
		background: '#CC00FF',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 200,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 100,
		background: '#996666',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 300,
		background: 'gray',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	},
	{
		height: 400,
		background: '#CC00FF',
		image: '/images/works-publicity/tradition.png',
		text: '平面作品+李宇轩',
	}
];
相关推荐
再玉米地里吃过亏36 分钟前
ONENET平台API鉴权错误
前端
网络点点滴38 分钟前
Vue3中Suspense的使用
前端·javascript·vue.js
饼干哥哥1 小时前
搭建一个云端Skills系统,随时随地记录TikTok爆款
前端·后端
酉鬼女又兒1 小时前
零基础快速入门前端Web存储(sessionStorage & localStorage)知识点详解与蓝桥杯考点应用(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·html
FollowHeart1 小时前
自建私有日记本:MyDiary —— 属于你的 NAS 极简写作空间
vue.js·github
DanCheOo1 小时前
# 从"会用 AI"到"架构 AI":高级前端的认知升级
前端·ai编程
社恐的下水道蟑螂2 小时前
前端面试必问 Git 通关指南:常用命令速查 + merge/rebase 深度辨析,看完再也不慌
前端·git·面试
angerdream2 小时前
最新版vue3+TypeScript开发入门到实战教程之组件通信之二
javascript·vue.js
小只笨笨狗~2 小时前
解决objectSpanMethod与expand共存时展开后表格错位问题
开发语言·javascript·ecmascript
None3212 小时前
NestJS 流式文件上传实践:从 Multer 到 Busboy 的进阶之路
前端·后端