Uniapp实现三列瀑布流布局(表格瀑布流)

本次主要实现的功能是一个三列的表格瀑布流布局。

实现效果图:

功能主要的重点就是每次拿到一条数据时,找出三列中高度最小的,然后往高度最小的插入这条数据。

首先先声明了几个变量做为数据处理

data() {
		return {
			columnCount: 3, // 默认列数
			columnHeights: [], // 记录每列的高度
			itemMargin: 25, // 元素间隙
			columnData: [[], [], []], // 三列数据
		}
},

因为做的是三列瀑布流,这里先定了3,同时需要获取到屏幕的宽度并进行平均分配,而为了适配不同的分辨率,写了一个rpx转换为px的方法,宽度的获取代码如下。

methods中写了一个rpx转换方法

adaptScreen(rpx) {
	return (uni.getSystemInfoSync().windowWidth * Number.parseInt(rpx)) / 750
},

computed中写了一个获取宽度的方法

getItemStyle() {
			let swiperWidth = parseInt(uni.getSystemInfoSync().windowWidth - this.adaptScreen(35))
			let swiperItem = parseInt((swiperWidth - (this.columnCount - 1) * this.itemMargin) / this.columnCount);
			return { width: swiperItem + 'px' };
},
核心代码

瀑布流的实现,我们需要每次都获取到最小的高度,然后往其中插入数据

首先调取接口获取到后端数据后,进行一个遍历循环,这里的this.mealList值是后端给的数据,循环中找出最小的高度的下标,然后往对应的this.columnData[对应的最小高度的下标]中插入数据,同时要更新下三列的高度(这里更新列的高度是拿到后端返回的表格数据的长度+表格标题)。

this.mealList.forEach((items) => {
	const columnIndex = this.getMinHeightColumnIndex();
	const columnHeight = this.columnHeights[columnIndex];
	const newItemHeight = (items.list.length + 1);
	this.columnHeights[columnIndex] = columnHeight + newItemHeight;
	this.columnData[columnIndex].push(items);
});
// 获取最小高度的列索引
getMinHeightColumnIndex() {
	let minHeight = this.columnHeights[0];
	let minIndex = 0;
	for (let i = 1; i < this.columnCount; i++) {
		if (this.columnHeights[i] < minHeight) {
			minHeight = this.columnHeights[i];
			minIndex = i;
		}
	}
	return minIndex;
},

全部代码如下

<template>
	<view class="home">
		<view class="homeBox">
			<view class="contentBox">
				<view class="mainContent">
					<view class="swiperTable">
						<view v-for="(columns, index) in columnCount" :style="[getItemStyle]" ref="columns" id="columns"
							:key="`swipers-1-${columns + 1}`">
							<view v-for="(datas) in columnData[index]" :key="datas.typeName" class="columnDataBox">
								<view class="tableTitle">{{ datas.typeName ? datas.typeName : '未分类' }}</view>
								<view class="tableContent" v-for="(nameList) in datas.list" :key="nameList.code">
									{{ nameList.name }}</view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
export default {
	data() {
		return {
			columnCount: 3, // 默认列数
			columnHeights: [], // 记录每列的高度
			itemMargin: 25, // 元素间隙
			columnData: [[], [], []], // 三列数据
		}
	},
	computed: {
		getItemStyle() {
			let swiperWidth = parseInt(uni.getSystemInfoSync().windowWidth -
				this.adaptScreen(35))
			let swiperItem = parseInt((swiperWidth - (this.columnCount - 1) *
				this.itemMargin) / this.columnCount);
			return { width: swiperItem + 'px' };
		},
	},
	mounted() {
		// 调取接口
		this.getMealListApi();
	},
	methods: {
		// rpx转换
		adaptScreen(rpx) {
			return (uni.getSystemInfoSync().windowWidth * Number.parseInt(rpx)) / 750
		},
		// 获取最小高度的列索引
		getMinHeightColumnIndex() {
			let minHeight = this.columnHeights[0];
			let minIndex = 0;
			for (let i = 1; i < this.columnCount; i++) {
				if (this.columnHeights[i] < minHeight) {
					minHeight = this.columnHeights[i];
					minIndex = i;
				}
			}
			return minIndex;
		},
		// 调取接口
		getMealListApi() {
			// 这里调后端接口 将数据复制给 this.mealList 
			// 下面的数据为自己造的假数据,实战中应调取接口
			this.mealList = [
				{
					typeName: '水果',
					list: [
						{ code: 1, name: '苹果' },
						{ code: 2, name: '梨' },
						{ code: 3, name: '草莓' },
						{ code: 4, name: '樱桃' },
						{ code: 5, name: '葡萄' },
					],
				},
				{
					typeName: '饮料',
					list: [
						{ code: 6, name: '可乐' },
						{ code: 7, name: '雪碧' },
						{ code: 8, name: '橙汁' },
						{ code: 9, name: '王老吉' },
						{ code: 10, name: '东鹏特饮' },
						{ code: 11, name: '红牛' },
						{ code: 12, name: '椰汁' },
					],
				},
				{
					typeName: '维生素',
					list: [
						{ code: 13, name: '维生素A' },
						{ code: 14, name: '维生素B' },
						{ code: 15, name: '维生素C' },
						{ code: 16, name: '维生素D' },
					],
				},
				{
					typeName: '书本',
					list: [
						{ code: 17, name: '语文书' },
						{ code: 18, name: '数学书' },
						{ code: 19, name: '英语书' },
					],
				},
				{
					typeName: '笔记本',
					list: [
						{ code: 20, name: '小笔记本' },
						{ code: 21, name: '大笔记本' },
					],
				},
				{
					typeName: '笔',
					list: [
						{ code: 22, name: '铅笔' },
						{ code: 23, name: '钢笔' },
						{ code: 24, name: '写字笔' },
						{ code: 25, name: '彩色笔' },
						{ code: 26, name: '水笔' },
						{ code: 27, name: '水墨笔' },
						{ code: 28, name: '签字笔' },
					],
				},
				{
					typeName: '棋子',
					list: [
						{ code: 29, name: '小棋子' },
					],
				},
				{
					typeName: '风扇',
					list: [
						{ code: 30, name: '小风扇' },
					],
				},
			];
			this.columnData = [[], [], []];
			this.columnHeights = new Array(this.columnCount).fill(0);
			this.mealList.forEach((items) => {
				const columnIndex = this.getMinHeightColumnIndex();
				console.log(columnIndex);
				const columnHeight = this.columnHeights[columnIndex];
				const newItemHeight = (items.list.length + 1);
				this.columnHeights[columnIndex] = columnHeight + newItemHeight;
				this.columnData[columnIndex].push(items);
				console.log(this.columnData);
			});
		},
	}
}
</script>
<style scoped lang="scss">
page {
	background: #E2EBF0;
}

.home {
	display: flex;
	flex-direction: column;

	.homeBox {
		height: calc(100vh - 15rpx);
		position: relative;

		.contentBox {
			width: 100%;
			height: 100%;
			margin-top: 4rpx;
			padding-left: 10rpx;
			padding-right: 6rpx;
			box-sizing: border-box;

			.mainContent {
				width: 100%;
				height: 100%;
				background: linear-gradient(90deg, #E7EEF6 0%, #EEF4F7 100%);
				box-shadow: -4rpx -4rpx 8rpx 0rpx rgba(252, 253, 254, 1), 4rpx 4rpx 8rpx 0rpx rgba(215, 225, 235, 1);
				border-radius: 6rpx;
				.swiperTable {
						width: 100%;
						// height: 100%;
						display: flex;
						justify-content: space-between;
						padding: 10rpx;
						box-sizing: border-box;

						.columnDataBox {
							margin-bottom: 5rpx;
							text-align: center;
							font-size: 8rpx;

							.tableTitle {

								border-top-left-radius: 4rpx;
								border-top-right-radius: 4rpx;
								background-color: #01b6fd;
								border-left: 1rpx solid #01b6fd;
								border-right: 1rpx solid #01b6fd;
								border-bottom: 1rpx solid #01b6fd;
								height: 20rpx;
								line-height: 20rpx;
								font-weight: bold;
								color: #fff;
							}

							.tableContent {
								// border: 1px solid #01b6fd;
								border-left: 1rpx solid #01b6fd;
								border-right: 1rpx solid #01b6fd;
								border-bottom: 1rpx solid #01b6fd;
								height: 18rpx;
								line-height: 18rpx;
								font-weight: bold;
							}
						}
					}
			}
		}

	}
}
</style>

最终实现的效果图

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值