EP30 实现预览页面切换

文件路径: E:/homework/uniappv3tswallpaper/pages/classlist/classlist.vue

navigator 标签的 url 属性中添加了 prop 参数,向子组件传递了 id

<template>
	<view class="classlist">
		<view class="loadingLayout" v-if="!classList.length && !noData">
			<uni-load-more status="loading"></uni-load-more>
		</view>
		<view class="content">
			<navigator :url="'/pages/preview/preview?id='+item._id" class="item" v-for="item in classList"
				:key="item._id">
				<image :src="item.smallPicurl" mode="aspectFill"></image>
			</navigator>
		</view>
		<view class="loadingLayout" v-if="classList.length || noData">
			<uni-load-more :status="noData? 'nomre':'loading'"></uni-load-more>
		</view>
	</view>
</template>

<script setup>
	import {
		ref
	} from 'vue'
	import {
		apiGetCLassList
	} from '@/api/apis.js'
	import {
		onLoad,
		onReachBottom
	} from '@dcloudio/uni-app'

	const queryParams = {
		pageNum: 1,
		pageSize: 12
	}
	const noData = ref(false)

	onLoad(e => {
		console.log(e)
		let {
			id = null,
				name = null
		} = e
		uni.setNavigationBarTitle({
			title: name
		})
		queryParams.classid = id

		getClassList()
	})

	// 触底获取新数据
	onReachBottom(() => {
		if (noData.value) {
			return
		}
		queryParams.pageNum++
		getClassList()
	})

	// 定义列表参数
	const classList = ref([])

	// 发请求获取数据
	const getClassList = async () => {
		let res = await apiGetCLassList(queryParams)
		classList.value = [...classList.value, ...res.data]
		uni.setStorageSync("storageClassList", classList.value)
		if (queryParams.pageSize > res.data.length) {
			noData.value = true
		}
	}
</script>

<style lang="scss">
	.classlist {
		.content {
			display: grid;
			grid-template-columns: repeat(3, 1fr);
			gap: 5px;
			padding: 5rpx;

			.item {
				height: 440rpx;
				width: 100%;

				image {
					height: 100%;
					width: 100%;
					display: block;
				}
			}
		}
	}
</style>

文件路径: E:/homework/uniappv3tswallpaper/pages/preview/preview.vue

接受了参数 id
将预览时蒙版上的当前 index 与图片的 index 绑定。
获取了当前 index 并展示相应的图片。

<template>
	<view class="">


		<view class="preview" @click="changeMask">
			<swiper circular="true" :current="currentIndex" @change="swiperChange">
				<swiper-item v-for="item in classList" :key="item._id">
					<view class="swiper-item">
						<image :src="item.picurl" mode="aspectFill"></image>
					</view>
				</swiper-item>
			</swiper>
		</view>
		<view class="mask" v-show="maskState">
			<view class="goback" :style="{top:getStatusBarHeight() + 'px', height: getTitleBarHeight() + 'px'}"
				@click="goBack">
				<uni-icons type="back" size="20" color="#fff"></uni-icons>
			</view>
			<view class="num">
				{{currentIndex + 1}} / {{classList.length}}
			</view>
			<view class="time">
				<uni-dateformat :date="new Date()" format="hh:mm" />
			</view>
			<view class="date">
				<uni-dateformat :date="new Date()" format="MM月dd日" />
			</view>
			<view class="footer">
				<view class="box" @click="open">
					<uni-icons type="info" size="28"></uni-icons>
					<view class="text">
						信息
					</view>
				</view>
				<view class="box" @click="clickScore">
					<uni-icons type="star" size="28"></uni-icons>
					<view class="text">
						评分
					</view>
				</view>
				<view class="box">
					<uni-icons type="download" size="28"></uni-icons>
					<view class="text">
						下载
					</view>
				</view>
			</view>
			<uni-popup ref="infoPopup" type="bottom">
				<view class="infoPopup">
					<view class="popHead">
						<view class="twoSide"> </view>
						<view class="title">
							壁纸信息
						</view>
						<view class="close twoSide" @click="clickInfoClose">
							<uni-icons type="closeempty" size="18" color="#999"></uni-icons>
						</view>
					</view>
					<view class="popContent">
						<scroll-view scroll-y show-scrollbar="false">
							<view class="content">
								<view class="row">
									<view class="label">
										壁纸ID:
									</view>
									<view class="labelContent">
										<text selectable="" class="value">165498642</text>
									</view>
								</view>
								<view class="row">
									<view class="label">
										分类:
									</view>
									<view class="labelContent">
										<text class="value">明星美女</text>
									</view>
								</view>
								<view class="row">
									<view class="label">
										发布者:
									</view>
									<view class="labelContent">
										<text class="value">呱呱呱</text>
									</view>
								</view>
								<view class="row">
									<view class="label">
										评分:
									</view>
									<view class="labelContent rateBox">
										<uni-rate readonly="true" touchable="true" value="3.6" size="16" />
										<text class="value">5分</text>
									</view>
								</view>
								<view class="row">
									<view class="label">
										摘要:
									</view>
									<view class="labelContent">
										<text
											class="value">摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要摘要</text>
									</view>
								</view>
								<view class="row">
									<view class="label">
										标签:
									</view>
									<view class="labelContent tabs" v-for="item in 3">
										<text class="value tab">标签名</text>
									</view>
								</view>
								<view class="copyright">
									建军事基地附件四哦那个佛哦放假哦计算机的佛i就哦i放到i杰佛i明尼苏达解耦i九年级哦i就欧锦好的话念佛哦你发的时间了哦ijoin的方式哦i
								</view>
							</view>
						</scroll-view>
					</view>
				</view>
			</uni-popup>
			<uni-popup ref="scorePopup" type="center" :is-mask-click="true">
				<view class="scorePopup">
					<view class="popHead">
						<view class="title_out">
							<view class="title">
								壁纸信息
							</view>
						</view>
						<view class="close" @click="clickScoreClose">
							<uni-icons type="closeempty" size="18" color="#999"></uni-icons>
						</view>
					</view>
					<view class="popContent">
						<view class="scoreStars">
							<uni-rate v-model="value" @change="scoreStarsChange" :value="scoreNumVal"
								allow-half="true" />
						</view>
						<view class="scoreNum">
							{{scoreNumVal}} 分
						</view>
					</view>
					<view class="scoreButton">
						<button class="subScore" @click="subScore" :disabled="!scoreNumVal">确认评分</button>
					</view>
				</view>
			</uni-popup>
		</view>

	</view>
</template>

<script setup>
	import {
		ref
	} from 'vue';
	import {
		getStatusBarHeight,
		getTitleBarHeight
	} from '@/utils/system.js'
	import {
		onLoad
	} from '@dcloudio/uni-app'

	const maskState = ref(true);
	const infoPopup = ref(null);
	const scorePopup = ref(null);
	const scoreNumVal = ref(0);
	const classList = ref([]);
	const currentId = ref(null)
	const currentIndex = ref(null)

	// 获取地址传递的参数
	onLoad((e) => {
		console.log(e.id)
		currentId.value = e.id
		currentIndex.value = classList.value.findIndex(item => item._id == currentId.value)
	})
	// 修改swiper的current
	const swiperChange = function(e) {
		currentIndex.value = e.detail.current
	}

	//读取本地存储
	let storageClassList = uni.getStorageSync("storageClassList")
	classList.value = storageClassList.map(item => {
		return {
			...item,
			picurl: item.smallPicurl.replace("_small.webp", ".jpg")
		}
	})
	console.log(classList.value)

	// 打开遮罩层
	const changeMask = () => {
		maskState.value = !maskState.value
	};
	// 打开信息层
	const open = () => {
		infoPopup.value.open()
	}
	// 关闭信息层
	const clickInfoClose = () => {
		infoPopup.value.close()
	}
	// 打开评分
	const clickScore = () => {
		scorePopup.value.open()
	}
	// 关闭评分
	const clickScoreClose = () => {
		scorePopup.value.close()
	}
	// score评分
	const scoreStarsChange = (e) => {
		scoreNumVal.value = e.value
	}
	// 点击确认提交
	const subScore = () => {
		console.log(scoreNumVal.value)
	}

	// 返回上一层
	const goBack = () => {
		uni.navigateBack();
	}
</script>

<style lang="scss" scoped>
	.preview {
		width: 100%;
		height: 100vh;

		swiper {
			width: 100%;
			height: 100%;

			.swiper-item {
				height: 100%;
				width: 100%;

				image {
					height: 100%;
					width: 100%;
				}
			}
		}
	}

	.mask {
		&>view {
			position: absolute;
			left: 0%;
			right: 0%;
			margin: auto;
			width: fit-content;
			color: #fff;
		}

		.goback {
			width: 79rpx;
			height: 79rpx;
			background: rgba(0, 0, 0, 0.5);
			left: 30rpx;
			margin-left: 0;
			border-radius: 100px;
			top: 0;
			backdrop-filter: blur(10rpx);
			border: 1rpx solid rbga(255, 255, 255, 0.3);
			display: flex;
			align-items: center;
			justify-content: center;
		}

		// position: relative; // 需要的是相对于整个屏幕的绝对位置,所以在这里不设置这个属性
		.num {
			top: 10vh;
			background: rgba(0, 0, 0, 0.3);
			backdrop-filter: blur(10rpx);
			padding: 8rpx 18rpx;
			border-radius: 40rpx;
			font-size: 28rpx;
		}

		.time {
			top: calc(10vh + 160rpx);
			font-size: 140rpx;
			font-weight: 100;
			line-height: 1rem;
			text-shadow: 0 4rpx rgba(0, 0, 0, 0.3);
		}

		.date {
			top: calc(10vh + 280rpx);
			font-size: 34rpx;
			text-shadow: 0 4rpx rgba(0, 0, 0, 0.3);
		}

		.footer {
			bottom: 10vh;
			background: rgba(255, 255, 255, 0.8);
			width: 65vw;
			height: 120rpx;
			border-radius: 120rpx;
			display: flex;
			flex-direction: row;
			flex-wrap: nowrap;
			align-content: center;
			justify-content: space-evenly;
			align-items: center;

			.box {
				display: flex;
				flex-direction: column;
				flex-wrap: nowrap;
				align-content: center;
				justify-content: center;
				align-items: center;
				padding: 2rpx 12rpx;

				.text {
					color: $text-font-color-2;
					font-size: 26rpx;
				}
			}
		}

		.infoPopup {
			background: #fff;
			padding: 30rpx;
			border-radius: 30rpx 30rpx 0 0;
			overflow: hidden;
			color: black;

			.popHead {
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				align-content: center;
				justify-content: space-between;
				align-items: center;


				.title {
					color: $text-font-color-2;
					font-size: 26rpx;
				}

				.close {
					// padding: 6rpx;
				}
			}

			.popContent {
				height: 60vh;

				scroll-view {
					height: 100%;

					.content {
						.row {
							display: flex;
							flex-direction: row;
							flex-wrap: nowrap;
							align-content: center;
							align-items: center;
							justify-content: center;
							padding: 16rpx 0;
							font-size: 32rpx;
							line-height: 1.7rem;

							.label {
								width: 25%;
								text-align: right;
								color: $text-font-color-3;
								font-size: 30rpx;
							}

							.labelContent {
								flex: 1;
								width: 0;
							}

							.rateBox {
								display: flex;
								flex-direction: row;
								flex-wrap: nowrap;
								align-content: center;
								justify-content: flex-start;
								align-items: center;

								.value {
									font-size: 26rpx;
									color: $text-font-color-3 ;
									padding-left: 25rpx;
								}
							}

							.tabs {
								display: flex;
								flex-wrap: wrap;

								.tab {
									border: 1px solid $brand-theme-color;
									color: $brand-theme-color;
									font-size: 22rpx;
									padding: 10rpx 30rpx;
									border-radius: 40rpx;
									line-height: 1rem;
									margin: 0 10rpx 10rpx 0;
									width: fit-content;
								}
							}
						}

						.copyright {
							font-size: 22rpx;
							padding: 20rpx;
							background: #f6f6f6;
							color: #666;
							border-radius: 10rpx;
							margin: 20rpx 0;
							line-height: 1.6rem;
							width: 100%;
						}
					}
				}
			}
		}

		.scorePopup {
			width: 70vw;
			height: 25vh;
			background-color: #fff;
			padding: 30rpx;
			border-radius: 30rpx;

			.popHead {
				display: flex;
				flex-wrap: wrap;
				flex-direction: row-reverse;

				.title_out {
					width: 100%;
					height: 0;

					.title {
						color: $text-font-color-2;
						font-size: 26rpx;
						text-align: center;
					}
				}

				.close {
					padding: 0 6rpx;
				}
			}

			.popContent {
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				align-content: center;
				justify-content: space-evenly;
				align-items: center;
				padding-top: 70rpx;

				.scoreNum {
					text-align: right;
					width: 100rpx;
					color: #feca43;
				}
			}

			.scoreButton {
				padding: 80rpx 70rpx 0 70rpx;
			}
		}
	}
</style>

注意:
遇到报错 Extraneous non-props attributes (id) were passed to component but could not be automatically inheri ,原因是父组件传递了一个prop参数,子组件中不止一个根节点,无法确定接收参数的节点。
解决办法是将子组件包裹在一个根节点中。所以在 preview 文件中可以看到最外层是一个没有类名的 view

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值