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: '平面作品+李宇轩',
	}
];
相关推荐
Мартин.3 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
昨天;明天。今天。4 小时前
案例-表白墙简单实现
前端·javascript·css
数云界4 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd4 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常4 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer4 小时前
Vite:为什么选 Vite
前端
小御姐@stella4 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing4 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing4 小时前
WebGL在低配置电脑的应用
javascript