[写微信小程序的第三天]模仿小红书写一个双列瀑布流页面!

先上效果图!

这个页面展示的原理是什么嘞?

其实就是将屏幕分为左右两大块,

然后判断左右两边加载的块块高度,

左边高了就加到右边的list,右边高了就加到左边的list(主打一个水多加面,面多加水),

这样就可以很灵活而且很平均啦!下面是js部分(这个双列瀑布流的精华计算部分,html的话,其实就是分别加载leftList跟rightList啦,全部代码会放在最下方)

<script>
	let query, leftHeight = 0 , rightHeight = 0;
	
	export default {
		data() {
			return {
				
					
				totalList:[],		// 所有数据
				leftList: [],		// 左边数据
				rightList: [],		// 右边数据
			}
		},
		mounted() {
			this.getDataDom()
		},
		methods: {
			async getDataDom() {
				let data = this.$data;
				query = uni.createSelectorQuery().in(this);
				for (let item in data.totalList) {
					// 判断两边的高度 看往什么list加
					leftHeight <= rightHeight ? data.leftList.push(data.totalList[item]) : data.rightList.push(data.totalList[item]);

					//加完计算左右的高度,好进行下一轮比较
					await this.getBoxHeight(data.leftList, data.rightList);
				}
			},
			
			getBoxHeight(leftList, rightList) {
				return new Promise((resolve, reject) => {
					this.$data.leftList = leftList
					this.$data.rightList = rightList
					query.select('#dis_left').boundingClientRect();
					query.select('#dis_right').boundingClientRect();
					// 处理异步问题,没有数据
					setTimeout(() => {
						query.exec((res) => {
							leftHeight = res[0].height; //获取左边列表的高度
							rightHeight = res[1].height; //获取右边列表的高度
							resolve();
						});
					})
				})
			}
		}
	}
</script>

 

OK!解决完这个页面最精华的问题,就可以调整一些细节,

例如每一卡片的高度,我设定的是文字类型就固定高度,图片类型就根据图片的高度来布置卡片,这样可以有些变化,不至于太死板,因此在我的html部分,又用了v-if来判断这么一张卡片是属于图片类型,还是文字类型的

还有个不太容易注意到的小细节就是,固定高度的话,假如文字特别长怎么办呢,一开始,我没有写overflow:hidden,文字直接飞出屏幕了,加上的话 我发现他不是从第一行开始显示的,因为我设置的是水平垂直居中,ok,前端水平欠缺的我直接是一个大求助gpt,嘿嘿嘿,真好用啊,学习利器

终于解决了展示的一些小小细节,在哪里发布图片其实也有很多选择,一开始,我是准备把
截图里"阿钙的留言板"换成发布文章的,有个问题就是,如果用户翻到很下边的地方,想发布文章,还得回到顶部,那不会很糟心吗,于是我否决了这个美丽的小想法,灵光一闪,想起小米的备忘录,觉得右下角加一个固定按钮设计还蛮不错的,因此使用了这个方案,css中fixed类型就能固定,ohhh!(一些页面设计的小小思路)

下面代码的页面分布模块,微微讲解一下,有时候看csdn上的有些文章会迷迷糊糊的(暖心)

html就分为,左边列表跟右边列表,然后每一边的view模块中又遍历leftList或者rightList(他们的区分就是在js中事先计算左右高度) 遍历的时候发现,欸有图片类型的信息,有文字类型的信息,分别塞入不同css的卡片中(文字卡片固定一个高度 图片卡片根据图片高度来) 卡片的下半部分,就是固定高度的用户跟用户名,右下角有个发布新留言按钮,没了没了,就是这样简单!

基本上这个页面的静态内容就是这样了,下面放所有代码!还没写后端,这个代码也是没有后端部分的,放心大胆的看!放心大胆的复制粘贴!放心大胆的点赞收藏!把图片url的部分替换,应该就可以直接在页面上看到效果啦!如果觉得有帮助的话可以给我点一个赞,我会很开心的,嘻嘻

<template>
	<view class="dislocat_content">
		<view id="dis_left" class="dislocat_content_left">
			
		<view class="border-outside" >
			<view class="top-card">
			      <view class="centered-text2">阿钙的<br/>留言板</view>
			  </view>
		</view>
			
			<view class="border-outside" v-for="(item,index) in leftList" >
				<!-- 文字类型信息 -->
				<view class="card" v-if="item.infoType=='0'">
				    <view class="top-section" >
				      <text class="centered-text">{{item.context}}</text>
				    </view>
					
					
				    <view class="bottom-section">
				      <view class="avatar-wrapper">
				        <image class="avatar" :src="item.src"  mode="aspectFill"></image>
				      </view>
				      <view class="name-wrapper">
				        <text class="name">{{item.userName}}</text>
				      </view>
				    </view>
				  </view>
				  
				  <view class="card1" v-if="item.infoType=='1'" >
				     
				  		<!-- 图片类型信息 -->
				  	<view class="top-section1" >
				  		<image class="img_icon" :src="item.photoUrl" mode="widthFix"></image>
				  	</view>
				  	
				      <view class="bottom-section">
				        <view class="avatar-wrapper">
				          <image class="avatar" :src="item.src"  mode="aspectFill"></image>
				        </view>
				        <view class="name-wrapper">
				          <text class="name">{{item.userName}}</text>
				        </view>
				      </view>
				    </view>
			</view>
			
			
			
		</view>
		
		<view id="dis_right" class="dislocat_content_right">
			<view class="border-outside" v-for="(item,index) in rightList" >
				<!-- 文字类型信息 -->
				<view class="card" v-if="item.infoType=='0'">
				    <view class="top-section" >
				      <text class="centered-text">{{item.context}}</text>
				    </view>
					
					
				    <view class="bottom-section">
				      <view class="avatar-wrapper">
				        <image class="avatar" :src="item.src"  mode="aspectFill"></image>
				      </view>
				      <view class="name-wrapper">
				        <text class="name">{{item.userName}}</text>
				      </view>
				    </view>
				  </view>
				  
				  <view class="card1" v-if="item.infoType=='1'" >
				     
				  		<!-- 图片类型信息 -->
				  	<view class="top-section1" >
				  		<image class="img_icon" :src="item.photoUrl" mode="widthFix"></image>
				  	</view>
				  	
				      <view class="bottom-section">
				        <view class="avatar-wrapper">
				          <image class="avatar" :src="item.src"  mode="aspectFill"></image>
				        </view>
				        <view class="name-wrapper">
				          <text class="name">{{item.userName}}</text>
				        </view>
				      </view>
				    </view>
			</view>
		</view>
	</view>
	
	  <!-- 固定在右下角的圆形按钮 -->
	       <view class="fixed-button">
	             <view class="circle">
	               +
	             </view>
	           </view>
	        
</template>

<script>
	let query, leftHeight = 0 , rightHeight = 0;
	
	export default {
		data() {
			return {
				totalList: [
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"0",
					context:"这是第一条信息",
					userName:"阿钙"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"0",
					context:"我喜欢吃椰子",
					userName:"coconutwy"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"0",
					context:"我爱打篮球",
					userName:"小蔡"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"1",
					photoUrl:"../../static/hxd.jpg",
					userName:"阿钙"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"0",
					context:"我笑死了,一个个都怕卷到自己,都劝退java,实际呢?还不是机械5k是东山再起,计算机20w尽显颓势。我小学毕业就出来打工四处碰壁,直到我碰见了余胜军,参加了java培训,毫不夸张,只要你好好学,出去两万是保底的事,都说java学的多,实际呢?也不过就spring,微服务,并发那些罢了,一个月学俩门,一个半月就能拿下,以后java必是蓝海专业,国家大力发展数字经济,所谓大佬也不过就是顺应局势罢了,当你们还在讨论今年java已死的时候,我已经拿到5个offer了,差距就是这样打开的",

					userName:"Java之父"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"0",
					context:"我爱吃钙片",
					userName:"阿钙"
					},{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"1",
					photoUrl:"../../static/hxd.jpg",
					userName:"阿钙"
					},
					{src:"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0",
					infoType:"1",
					photoUrl:"../../static/hxd.jpg",
					userName:"阿钙"
					},
					
				],		// 所有数据
				leftList: [],		// 左边数据
				rightList: [],		// 右边数据
			}
		},
		mounted() {
			this.getDataDom()
		},
		methods: {
			async getDataDom() {
				let data = this.$data;
				query = uni.createSelectorQuery().in(this);
				for (let item in data.totalList) {
					// 判断两边的高度
					leftHeight <= rightHeight ? data.leftList.push(data.totalList[item]) : data.rightList.push(data.totalList[item]);
					
					await this.getBoxHeight(data.leftList, data.rightList);
				}
			},
			
			getBoxHeight(leftList, rightList) {
				return new Promise((resolve, reject) => {
					this.$data.leftList = leftList
					this.$data.rightList = rightList
					query.select('#dis_left').boundingClientRect();
					query.select('#dis_right').boundingClientRect();
					// 处理异步问题,没有数据
					setTimeout(() => {
						query.exec((res) => {
							leftHeight = res[0].height; //获取左边列表的高度
							rightHeight = res[1].height; //获取右边列表的高度
							resolve();
						});
					})
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	.dislocat_content{
		width: 100%;
		position: relative;
		overflow: hidden;
		box-sizing: border-box;
		&_left, &_right{
			width: 48.2%;
			float: left;
			border-radius: 10rpx;
		}
		&_left{
			margin-left: 1.2%;
			margin-right: 0.6%;
		}
		&_right{
			margin-right: 1.2%;
			margin-left: 0.6%;
		}
		.border-outside{
			margin-top: 14rpx;
			.img_icon{
				width: 100%;
				display: block;
				border-radius: 10rpx;
			}
			
		}
	}
	
	.card {
	  width: 100%;
	  height: 550rpx;
	  background-color: white;
	  border: 1px solid #ff557f;
	  border-radius: 20rpx; /* 整体卡片的圆角 */
	  box-shadow: 2rpx 6rpx 8rpx rgba(0, 0, 0, 0.1); /* 卡片的阴影 */
	  padding:0 20rpx; /* 卡片内部的内边距 */
	  box-sizing: border-box; /* 使padding不影响卡片的总宽度 */
	}
	.card1 {
	  
	  width: 100%;
	    min-height: 0; /* 添加最小高度限制 */
	    background-color: white;
	    border: 1px solid #ff557f;
	    border-radius: 20rpx; /* 整体卡片的圆角 */
	    box-shadow: 2rpx 6rpx 8rpx rgba(0, 0, 0, 0.1); /* 卡片的阴影 */
	    padding: 20rpx; /* 卡片内部的内边距 */
	    box-sizing: border-box; /* 使padding不影响卡片的总宽度 */
	}
	
	.top-card{
		width: 100%;
		height: 300rpx;
		background-color: white;
		border: 3px solid #ff557f;
		border-radius: 20rpx; /* 整体卡片的圆角 */
		box-shadow: 2rpx 6rpx 8rpx rgba(0, 0, 0, 0.1); /* 卡片的阴影 */
		padding: 20rpx; /* 卡片内部的内边距 */
		box-sizing: border-box; /* 使padding不影响卡片的总宽度 */
		display: flex;
		justify-content: center;
		align-items: center;
		background-color:rgba(255, 182, 193, 0.3);
		
		
	}
	
	
	
	.top-section {
	  height: 390rpx; /* 上部分高度占比 */
	  padding: 20rpx 0;
	  display: flex;
	  justify-content: center;
	  align-items: center;
	  overflow: hidden;
	    
	 
	}
	
	.top-section1 {
	margin-bottom: 20rpx;
	   flex: 1; /* 占据剩余空间 */
	    display: flex;
	    justify-content: center;
	    align-items: center;
	 
	}
	
	.centered-text {
	  font-size: 30rpx;
	  color: #333;
	  display: -webkit-box; /* 使用flexbox布局 */
	    -webkit-box-orient: vertical; /* 垂直方向 */
	    -webkit-line-clamp: 10; /* 最多显示两行 */
	    overflow: hidden; /* 超出部分隐藏 */
	}
	
	.centered-text2 {
	  font-size: 80rpx;
	  color: #ffffff;
	   text-shadow: 
	      -1px -1px 0 #000,  
	      1px -1px 0 #000,
	      -1px 1px 0 #000,
	      1px 1px 0 #000; /* 设置文字描边 */
	}
	
	.bottom-section {
	  height: 100rpx; /* 下部分高度占比 */
	  display: flex;
	  align-items: center;
	  background-color: rgba(255, 182, 193, 0.3); /* 圆角透明的灰粉色背景 */
	  border-radius: 20rpx; /* 下部分背景的圆角 */
	  padding: 0 20rpx; /* 下部分的左右内边距 */
	  box-sizing: border-box; /* 使padding不影响元素的总宽度 */
	}
	
	.avatar-wrapper {
	  flex: 0 0 auto; /* 固定大小,不缩放 */
	  width: 50rpx;
	  height: 50rpx;
	  margin-right: 20rpx; /* 右边的间距 */
	  border-radius: 50%; /* 头像框的圆形 */
	  overflow: hidden;
	}
	
	.avatar {
	  width: 100%;
	  height: 100%;
	}
	
	.name-wrapper {
	  flex: 1; /* 占据剩余空间 */
	  display: flex;
	  align-items: center;
	}
	
	.name {
	  font-size: 28rpx;
	  color: #333;
	}
	
	
	.fixed-button {
	  position: fixed; /* 固定定位,始终在视窗右下角 */
	  right: 50rpx; /* 距离视窗右侧的距离 */
	  bottom: 50rpx; /* 距离视窗底部的距离 */
	  z-index: 1000; /* 确保按钮在其他内容之上 */
	width: 120rpx; /* 圆形按钮的直径 */
	height: 120rpx; /* 圆形按钮的直径 */
	background-color: #ff557f; /* 圆形按钮的背景色 */
	border-radius: 50%; /* 让正方形变成圆形 */
	display: flex;
	justify-content: center;
	align-items: center;
	box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
	
	  /* 圆形按钮样式 */
	  .circle {
	    
		font-size: 60rpx; /* 加号的字体大小 */
		font-weight: bold;
		color: white; /* 加号的颜色 */
	  }
	
	 
	}
</style>


之后会做发布留言的页面,包括这个卡片点开的样子,不想跟小红书做的一模一样,可能点开会是一个弹出层的设计,然后能够像朋友圈一样被评论(纯纯自娱自乐的功能哈哈哈哈哈哈),具体的还得构想构想!接下来想引入一些动画什么的,看看能不能做出一些有趣的效果吧

“小书”——给你安利几个小程序的“坑”微信小程序在前面  小程序发布至今已有一年多时间,很多人都已经在小程序道路上狂奔。最近我也开始了学习小程序,学了一段时间后,想看看这段时间的学习效果,于是边学习边开始了我的第一个小程序。相信很多人都用过小书吧,我可是被它安利了很多好东西呢,所以想着就仿一个小书的微信小程序吧。下面我就给大家“安利”几个我在的过程中的“坑”。  因为花的时间不多,功能有很多没有完善,页面的不是很好看,请各位将就着看啦。╮(╯▽╰)╭   准备工作  1. 开发环境:WXML(HTML),WXSS(CSS),Javascript  2. 开发工具:vscode,微信开发者工具  3. 辅助工具:Markman:图标标注工具,可用于取色、测量。Easy-Mock:可以伪造假数据,在js中引用就好了。点这里可以查看我的项目数据。Markdown:在线编辑器GifCam:Gif录制工具 微信小程序开发文档Iconfont-阿里巴巴矢量图标库:各种需要的小图标都有哦遇到的几个问题1、首页导航栏左右滑动效果图:  这部分,是通过微信小程序的scroll-view组件来完成的。代码如下:<scroll-view class="navBar-box" scroll-x="true"  一些使用scroll-view的注意事项:请勿在 scroll-view 中使用 textarea、map、canvas、video 组件scroll-into-view 的优先级高于 scroll-top在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中滚动,是无法触发 onPullDownRefresh若要使用下拉刷新,请使用页面的滚动,而不是 scroll-view ,这样也能通过点击顶部状态栏回到页面顶部2、首页文章表随着点击导航栏表改变效果图:  这部分,是通过微信小程序的swiper组件来完成的。代码如下:                                                                                                    {{notes.title}}                              <!-- 作者信息 -->                                              {{notes.writer}}                                                {{notes.like}}                                    使用swiper组件,将所有文章表包起来,每个swiper-item表示不同的表模块。之前在导航栏各表项绑定了不同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值