vue3 uniapp封装一个瀑布流组件


新增组件m-waterfall   这样就可以在页面直接使用 不用在引入了
<template>
	<view class="m-waterfall">
		<view id="m-left-column" class="m-column">
			<slot name="left" :leftList="leftList"></slot>
		</view>
		<view id="m-right-column" class="m-column">
			<slot name="right" :rightList="rightList"></slot>
		</view>

	</view>
</template>

<script setup>
/**
 * @param value  瀑布流数据
 * @param addTime 插入数据的时间间隔
 * @param keyIdData / id值,用于清除某一条数据时,根据此idKey名称找到并移除
 */

import {
		computed,
		defineProps,
		toRefs
	} from "vue"

	
	const props=defineProps({
		// 瀑布流数据
		value: {
			 required: true,
			type: Array,
			default: ()=>[]
		},
		// 每次向结构插入数据的时间间隔,间隔越长,越能保证两列高度相近,但是对用户体验越不好
		addTime: {
			type: [Number, String],
			default: 200
		},
		// id值,用于清除某一条数据时,根据此idKey名称找到并移除
		keyIdData: {
			type: String,
			default: 'id'
		}
	})
	const {
		value,
		addTime,
		keyIdData
	} = toRefs(props)
	const leftList = ref([])
	const rightList = ref([])
	const tempList = ref([])
	const pendingImages = ref(new Map()) // 用于追踪待加载的图片
	const copyFlowList= computed (()=> {
		return cloneData(value.value);
	})
// 记录正在加载的图片数量
	const loadingCount = ref(0)
	// 处理图片加载完成事件
	const preloadImage = async (item) => {
	  return new Promise((resolve) => {
	      if (!item.image) {
	        resolve(item)
	        return
	      }
	  
	      // 如果这个图片已经在加载中,返回现有的 promise
	      if (pendingImages.value.has(item.image)) {
	        return pendingImages.value.get(item.image)
	      }
	  
	      const promise = new Promise((resolveImage) => {
	        uni.getImageInfo({
	          src: item.image,
	          success: (res) => {
	            // 保存图片的实际尺寸信息到 item
	            item.imageWidth = res.width
	            item.imageHeight = res.height
	            pendingImages.value.delete(item.image)
	            resolveImage(item)
	          },
	          fail: () => {
	            pendingImages.value.delete(item.image)
	            resolveImage(item)
	          }
	        })
	      })
	  
	      pendingImages.value.set(item.image, promise)
	      resolve(promise)
	    })
	}
	// const emit=defineEmits(['handleImageLoad'])
	watch(()=>value.value,(nVal,oVal)=>{
		let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
		
		tempList.value = tempList.value.concat(cloneData(nVal.slice(startIndex)));
		splitData();
	
	})
	onMounted(()=>{
	
		tempList.value = cloneData(copyFlowList.value);
		setTimeout(()=>{
			splitData();
		},200)
	})
	
const instance = getCurrentInstance()

	
	const getColumnHeight = (columnId) => {
	  return new Promise((resolve) => {
	    uni.createSelectorQuery()
	      .in(instance)
	      .select(columnId)
	      .boundingClientRect(data => {
	        resolve(data ? data.height : 0)
	      })
	      .exec()
	  })
	}
	const splitData = async () => {
	
		if (tempList.value.length === 0) return
		
		  const item = tempList.value[0]
		  if (!item) return
		
		  try {
		    // 等待图片预加载完成
		    await preloadImage(item)
		
		    // 获取两列的高度
		    const [leftHeight, rightHeight] = await Promise.all([
		      getColumnHeight('#m-left-column'),
		      getColumnHeight('#m-right-column')
		    ])
		
		    // 根据高度决定放入哪一列
		    if (leftHeight <= rightHeight) {
		      leftList.value.push(item)
		    } else {
		      rightList.value.push(item)
		    }
		
		    // 移除已处理的项目
		    tempList.value.splice(0, 1)
		
		    // 继续处理下一个项目
		    if (tempList.value.length) {
		      setTimeout(() => {
		        splitData()
		      }, Number(props.addTime))
		    }
		  } catch (error) {
		    console.error('Error in splitData:', error)
		    // 发生错误时也移除当前项目,继续处理下一个
		    tempList.value.splice(0, 1)
		    if (tempList.value.length) {
		      splitData()
		    }
		  }

	}
	// 复制而不是引用对象和数组
	const cloneData=(data)=>{
		if(data){
			return JSON.parse(JSON.stringify(data));
		}else{
			return [];
		}
		
	}
	
</script>

<style lang="scss" scoped>

.m-waterfall {
	margin-top: 20rpx;
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 10rpx;
}
 
.m-column {
	display: flex;
	flex: 1;
	flex-direction: column;
	height: auto;
}
 
.m-image {
	width: 100%;

}
</style>

组件使用

<m-waterfall :value="product">
				<!-- 左边数据 -->
				<template v-slot:left="{leftList}">
					<view @click="addDta" class="prodecutitem" v-for="(item,index) in leftList" :key="index">
						<view style="width: 100%;">
							<m-imgage :url="item.image"></m-imgage>
						</view>
						<view class="title">{{item.title}}</view>
						<view class="desc">{{item.title}}</view>
					</view>
				</template>
				<!-- 右边数据 -->
				<template v-slot:right="{rightList}">
					<view class="prodecutitem" v-for="(item,index) in rightList" :key="index">
						<view>
							<m-imgage :url="item.image"></m-imgage>
						</view>
						<view class="title">{{item.title}}</view>
						<view class="desc">{{item.title}}</view>
					</view>
				</template>
			</m-waterfal>

数据
	const product=ref([
		{
			title:'水果蔬菜1',
			image:imgSrc.value
		},
		{
			title:'水果蔬菜2',
			image:"https://img2.baidu.com/it/u=3893165480,918722033&fm=253&fmt=auto&app=120&f=JPEG?w=729&h=1215"
		},
		{
			title:'水果蔬菜3',
			image:imgSrc.value
		},
		{
			title:'水果蔬菜1',
			image:imgSrc.value
		},
		{
			title:'水果蔬菜3',
			image:imgSrc.value
		}
	])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

复杂 C++ 项目堆栈保留以及 eBPF 性能分析

在构建和维护复杂的 C 项目时&#xff0c;性能优化和内存管理是至关重要的。当我们面对性能瓶颈或内存泄露时&#xff0c;可以使用eBPF&#xff08;Extended Berkeley Packet Filter&#xff09;和 BCC&#xff08;BPF Compiler Collection&#xff09;工具来分析。如我们在Red…

unity学习18:unity里的 Debug.Log相关

目录 1 unity里的 Debug.log相关 2 用Debug.DrawLine 和 Debug.DrawRay画线 2.1 画线 1 unity里的 Debug.log相关 除了常用的 Debug.Log&#xff0c;还有另外2个 Debug.Log("Debug.Log"); Debug.LogWarning("Debug.LogWarning"); Debug.LogErro…

IoTDB 常见问题 QA 第三期

关于 IoTDB 的 Q & A IoTDB Q&A 第三期持续更新&#xff01;我们将定期汇总我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;查询最新值 & null 数据相加方…

MySQL数据库(SQL分类)

SQL分类 分类全称解释DDLData Definition Language数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09;DMLData Manipulation Language数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQLData Query Languag…

Swift 趣味开发:查找拼音首字母全部相同的 4 字成语(上)

概述 Swift 语言是一门现代化、安全、强大且还算性感的语言。在去年 WWDC 24 中苹果正式推出了秃头码农们期待许久的 Swift 6.0&#xff0c;它进一步完善了 Swift 语言的语法和语义&#xff0c;并再接再厉——强化了现代化并发模型的安全性和灵活性。 这里我们不妨用 Swift 来…

C++ STL之容器介绍(vector、list、set、map)

1 STL基本概念 C有两大思想&#xff0c;面向对象和泛型编程。泛型编程指编写代码时不必指定具体的数据类型&#xff0c;而是使用模板来代替实际类型&#xff0c;这样编写的函数或类可以在之后应用于各种数据类型。而STL就是C泛型编程的一个杰出例子。STL&#xff08;Standard …

VUE3 + Ant Design Vue4 开发笔记

异常记录 [Vue warn]: Extraneous non-props attributes (options) were passed to component but could not be automatically inherited because component renders fragment or text root nodes 定位原因解决方法 错误的中文释义&#xff1a;[Vue 警告]&#xff1a;传递给…

QT跨平台应用程序开发框架(2)—— 初识QT

目录 一&#xff0c;创建helloworld 1.1 通过图形化 1.2 通过代码 1.3 通过编辑框 1.4 使用按钮 二&#xff0c;对象树 2.1 关于对象树 2.2 演示释放流程 三&#xff0c;乱码问题 3.1 为什么会有乱码问题 3.2 解决乱码问题 四&#xff0c;认识Qt坐标系 五&#xf…

【搭建JavaEE】(3)前后端交互,请求响应机制,JDBC数据库连接

前后端交互 Apache Tomat B/S目前主流。 tomat包含2部分&#xff1a; apache容器 再认识servlet 抽象出的开发模式 项目创建配置 maven javaeetomcat 忽略一些不用的文件 webapp文件夹 HiServlet 这里面出现了webinfo&#xff0c;这个别删因为这个呢&#xff0c;是这这个这…

美摄科技PC端视频编辑解决方案,为企业打造专属的高效创作平台

在当今这个信息爆炸的时代&#xff0c;视频已成为不可或缺的重要内容形式&#xff0c;美摄科技推出了PC端视频编辑解决方案的私有化部署服务&#xff0c;旨在为企业提供一款量身定制的高效创作平台。 一、全面功能&#xff0c;满足企业多样化需求 美摄科技的PC端视频编辑解决…

探索图像编辑的无限可能——Adobe Photoshop全解析

文章目录 前言一、PS的历史二、PS的应用场景三、PS的功能及工具用法四、图层的概念五、调整与滤镜六、创建蒙版七、绘制形状与路径八、实战练习结语 前言 在当今数字化的世界里&#xff0c;视觉内容无处不在&#xff0c;而创建和编辑这些内容的能力已经成为许多行业的核心技能…

STM32-笔记41-RTC(实时时钟)

一、什么是RTC&#xff1f; 实时时钟的缩写是RTC(Real_Time Clock)。RTC 是集成电路&#xff0c;通常称为时钟芯片。 实时时钟是一个独立的定时器。 RTC模块拥有一组连续计数的计数器&#xff0c;在相应软件配置下&#xff0c;可提供时钟日历的功能。修改计数器的值可以重新设…

51c自动驾驶~合集46

我自己的原文哦~ https://blog.51cto.com/whaosoft/13050104 #世界模型会是L3自动驾驶的唯一解吗 三维空间占有率&#xff08;3D Occupancy&#xff09;预测的目的是预测三维空间中的每个体素是否被占有&#xff0c;如果被占有&#xff0c;则对应的体素将被标记。3D Semant…

mybatis-spring @MapperScan走读分析

接上一篇文章&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145100531&#xff0c; 本文注解分析mybatis-spring中的MapperScan注解&#xff0c;则将容易许多。 目录 MapperScan注解定义ConfigurationClassPostProcessor扫描注册beanDefinitionorg.mybatis.s…

Apache PAIMON 学习

参考&#xff1a;Apache PAIMON&#xff1a;实时数据湖技术框架及其实践 数据湖不仅仅是一个存储不同类数据的技术手段&#xff0c;更是提高数据分析效率、支持数据驱动决策、加速AI发展的基础设施。 新一代实时数据湖技术&#xff0c;Apache PAIMON兼容Apache Flink、Spark等…

SQL面试题1:连续登陆问题

引言 场景介绍&#xff1a; 许多互联网平台为了提高用户的参与度和忠诚度&#xff0c;会推出各种连续登录奖励机制。例如&#xff0c;游戏平台会给连续登录的玩家发放游戏道具、金币等奖励&#xff1b;学习类 APP 会为连续登录学习的用户提供积分&#xff0c;积分可兑换课程或…

电商系统,核心通用架构案例设计方案浅析

文章目录 一、用户系统案例设计1、用户信息的存储方案2、用户注册确保唯一3、用户数据合并方案4、用户敏感信息加密存储5、数据传输安全性6、多用户数据隔离性7、防止恶意注册8、用户好友关系存储方案9、用户登录token方案10、会员优先处理设计 二、网关系统设计1、网关的功能2…

【EI 会议征稿】第四届材料工程与应用力学国际学术会议(ICMEAAE 2025)

2025 4th International Conference on Materials Engineering and Applied Mechanics 重要信息 大会官网&#xff1a;www.icmeaae.com 大会时间&#xff1a;2025年3月7-9日 大会地点&#xff1a;中国西安 截稿时间&#xff1a;2025年1月24日23:59 接受/拒稿通知&#xf…

SQL面试题2:留存率问题

引言 场景介绍&#xff1a; 在互联网产品运营中&#xff0c;用户注册量和留存率是衡量产品吸引力和用户粘性的关键指标&#xff0c;直接影响产品的可持续发展和商业价值。通过分析这些数据&#xff0c;企业可以了解用户行为&#xff0c;优化产品策略&#xff0c;提升用户体验…

【Rust自学】11.7. 按测试的名称运行测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.7.1. 按名称运行测试的子集 如果想要选择运行的测试&#xff0c;就将测试的名称&#xff08;一个或多个&#xff09;作为cargo test的…