uni-app--》打造个性化壁纸预览应用平台(三)

news2024/9/20 5:32:02

🏙️作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名前端工程师

🌄个人主页:亦世凡华、

🌆系列专栏:uni-app

🌇座右铭:人生亦可燃烧,亦可腐败,我愿燃烧,耗尽所有光芒。

👀引言

⚓经过web前端的学习,相信大家对于前端开发有了一定深入的了解,今天我开设了uni-app专栏,对于想从移动端开发方向进一步发展的朋友,希望看到我文章的朋友能对你有所帮助。

        今天开始使用vue3+uni-app搭建一个电商购物的小程序,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的github上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端uni-app知识。

        如果是第一次接触uni-app并且想学习uni-app的朋友,我是不建议直接从此次实战项目开始看起,可以先阅读一下我以前的基础文章:什么是uniapp?如何开发uniapp? 按部就班的学习可以让学习变得更轻松更容易上手哦,闲话少说我们直接开始今天的uni-app实战篇。

目录

🏔️封装request请求

🌋分类页数据渲染

🗻预览页数据渲染

🏖️预览图信息渲染


🏔️封装request请求

通常我们使用vue封装请求库的时候,一般都会使用axios进行请求的封装,由于这里我们使用uni进行请求,所以这里我们就封装一下关于uni的request请求的封装,这里我们新建request封装的请求库,在utils文件夹下新建request.js,具体的代码如下所示:

// 封装请求库
const BASE_URL = '根路径'
const request = (config={}) => {
	let { url, method="GET", data={}, header={} } = config 
	
	header['access-key'] = "591938"
	return new Promise((resolve, reject) => {
		uni.request({
			url: BASE_URL + url,
			method: method,
			data: data,
			header: header,
			success: res => {
				if (res.data.errCode === 0) {
					resolve(res.data)
				} else if (res.data.errCode === 400) {
					uni.showModal({
						title: "错误提示",
						content: res.data.errMsg,
						showCancel: false
					})
					reject(res.data)
				} else {
					uni.showToast({
						title: res.data.errMsg,
						icon: "none"
					})
					reject(res.data)
				}
			},
			fail: err => {
				reject(err)
			}
		})
	})
}

export default request

然后我们在根目录下新建api文件夹,里面新建类似home.js的代表模块的api请求,关于首页的几个使用到的请求,这里在home.js文件夹中书写,内容如下所示:

import request from "@/utils/request.js"

// 获取轮播图数据
export function apiGerBanner() {
	return request({
		url: '/homeBanner'
	})
}

// 获取每日推荐数据
export function apiGetDayRandom() {
	return request({
		url: '/randomWall'
	})
}

// 获取专题精选数据
export function apiGetNotice(data={}) {
	return request({
		url: '/wallNewsList',
		data
	})
}
// 获取壁纸分类数据
export function apiGetClassify(data={}) {
	return request({
		url: '/classify',
		data
	})
}

封装完请求并写完接口函数之后,我们回到首页的组件中开始调用这些api函数,这里我们通过一个promises进行同步执行这些接口函数,优化执行时间:

<script setup>
import { ref, onMounted } from 'vue'
import { apiGerBanner, apiGetDayRandom, apiGetNotice, apiGetClassify } from '@/api/home.js'

const bannerList = ref([]) // 轮播图数据
const randomList = ref([]) // 随机九张图片
const noticeList = ref([]) // 专题精选数据
const classifyList = ref([]) // 专题精选数据

const getHomeData = async () => {
	let banner = await apiGerBanner()
	let random = await apiGetDayRandom()
	let notice = await apiGetNotice({select:true})
	let classify = await apiGetClassify({select: true})
    // 等待所有请求完成,不会因为某个 Promise 失败而导致整个操作失败
    const results = await Promise.allSettled([banner, random, notice, classify]);
	console.log("结果",results)
	// 处理每个请求的结果
	results.forEach((result, index) => {
	    if (result.status === 'fulfilled') {
	      // 请求成功
	      switch (index) {
	        case 0:
				bannerList.value = result.value.data || [];
				break;
	        case 1:
				randomList.value = result.value.data || [];
				break;
	        case 2:
				noticeList.value = result.value.data || [];
				break;
			case 3:
				classifyList.value = result.value.data || [];
				break;
	        default:
	            break;
	      }
	    } else {
	        // 请求失败
	        console.error(`Request ${index} failed:`, result.reason);
	    }
	});
}
	
onMounted(() => {
	getHomeData()
})
</script>

拿到接口数据之后,接下来开始在html中 通过v-for循环渲染相应的数据,代码如下所示:

然后我们在对应的组件中拿到数据进行渲染,最终呈现的效果如下所示:

🌋分类页数据渲染

传参加载数据:当然分类页面也是用到了首页主题精选相同的api函数,这里我们也是简单的调用一下然后渲染数据即可:

<script setup>
import { ref, onMounted } from 'vue'
import { apiGetClassify } from '@/api/home.js'
const classifyList = ref([]) // 专题精选数据
	
const getClassify = async () => {
	let res = await apiGetClassify({ pageSize: 15 })
	classifyList.value = res.data
}

onMounted(() => {
	getClassify()
})
</script>

最终呈现的效果如下所示:

接下来我们开始给分类页面设置跳转页面的时候进行传参,传递的参数就是当前图片的一个id和name数据,该数据我们通过后端返回给我们的每一张图片的id作为参数即可,如下所示:

然后这里我们使用uni自带的api函数onLoad进行获取传递的参数数据,当然也可以使用props来获取传递的数据,这里不再赘述,这里我们拿到相应的id和name的数据之后,就可以调用接口函数拿到对应的数据然后通过name来设置title标题:

<script setup>
import { ref } from 'vue'	
import { onLoad } from "@dcloudio/uni-app"
import { apiGetClassList } from '@/api/classlist.js'

const classList = ref([])
const queryParams = {}

// 获取分类列表数据
const getClassList = async () => {
	let res = await apiGetClassList(queryParams)
	classList.value = res.data
}

onLoad((e)=> {
	let { id = null, name=null } = e
	queryParams.classid = id
	// 修改当前分类列表页面的标题
	uni.setNavigationBarTitle({
		title: name
	})
	getClassList()
})
</script>

最终呈现的效果如下所示:

下拉触底加载更多: 接下来我们开始使用uni自带的下拉触底的api函数onReachBottom来获取更多的数据,这里我们通过设置参数,当每次触底的时候对pageNum进行++操作,默认触底的时机为false,如果变成true的话说明我们的数据以及加载完毕,就不需要再对pageNum进行++操作,如下:

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

onReachBottom(() => {
	if (noData.value) return 
	queryParams.pageNum++
	getClassList()
})
</script>

这里我们通过下拉触底获取到的数据对原数据进行一个凭借操作:

// 获取分类列表数据
const getClassList = async () => {
	let res = await apiGetClassList(queryParams)
	classList.value = [...classList.value, ...res.data]
	if (queryParams.pageSize > res.data.length) noData.value = true // 最后的数据小于最初设置的大小
}

最终呈现的效果如下所示:

loading操作:如果网速较慢的情况下,加载数据页面可能就会呈现空白界面,这样的用户体验可能就不是很好,这里我们可以通过设置骨架屏的操作提高用户体验,这里我们通过uni提供的一个插件进行操作,如下所示:

如果想使用加载的时候的loading的操作,这里我们可以使用uni官网提供的插件进行操作,如下:

然后这里我们在分类列表页面的图片内容上下分别设置加载组件,根据是否图片列表有数据和是否触底来实现加载的显示隐藏以及状态的改变,代码如下所示:

<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" 
				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 ? 'noMore' : 'loading'"></uni-load-more>
		</view>
		<view class="safe-area-insert-bottom"></view>
	</view>
</template>

最终呈现的效果如下所示:

🗻预览页数据渲染

为了避免我们在进行预览图片时切换图片可能会多次请求接口数据造成资源的浪费,这里我们把第一次请求图片的接口数据存放在本地当中,然后在预览图片的时间直接从本地获取到即可,这里我们借助uni提供的保存本地数据的接口:

然后我们在预览图片的组件当中,拿到本地资源的数据然后赋值给响应式ref当中:

const classList = ref([]) // 预览图片数据
const storgClassList = uni.getStorageSync("storgClassList") || [] // 缓存中的数据
classList.value = storgClassList.map(item => {
	return {
		...item,
		picurl: item.smallPicurl.replace("_small.webp", ".jpg")
	}
})

为了知道我们在预览图片的时候预览到第几张图片,这里我们把图片的id传递过去:

我们调用uni提供的onLoad函数,拿到传递过来的id数据与本地资源数组数据中进行比较,拿到当前图片id在本地资源数组数据中的索引:

onLoad((e) => {
	currentId.value = e.id
	currentIndex.value = classList.value.findIndex(item => item._id == currentId.value)
})

然后我们把当前的索引和图片总数据获取,然后渲染到页面上,当我们切换滑块的时候可以设置监听函数,如下所示:

通过移动滑块来改变当前的索引状态:

const swiperChange = (e) => {
	currentIndex.value = e.detail.current
}

最终呈现的效果如下所示:

上面实现的图片预览是一次性把所有图片全部缓存在本地然后进行预览,也会造成不必要的资源浪费,能不能我们使用就是当点击预览的时候,只会加载当前预览图片以后前后两张图片呢?这里我们可以通过获取当前预览图片及前后两张图片的索引,然后再判断当前预览的图片是否包含在我们设置的预览图片的数组当中,如果存在再请求图片资源,这样就会减少不必要的资源消耗:

const readImgFun = () => {
	readImgs.value.push(
		currentIndex.value <= 0 ? classList.value.length-1 : currentIndex.value-1,
		currentIndex.value,
		currentIndex.value >= classList.value.length-1 ? 0 : currentIndex.value+1
	)
	readImgs.value = [...new Set(readImgs.value)]
}

onLoad((e) => {
	currentId.value = e.id
	currentIndex.value = classList.value.findIndex(item => item._id == currentId.value)
	readImgFun()
})

const swiperChange = (e) => {
	currentIndex.value = e.detail.current
	readImgFun()
}

只渲染包含在数组当中索引的图片,如下所示:

🏖️预览图信息渲染

预览图片设置完成之后,接下来开始对预览图片上的相关信息进行设置,如下:

onLoad((e) => {
	currentId.value = e.id
	currentIndex.value = classList.value.findIndex(item => item._id == currentId.value)
	currentInfo.value = classList.value[currentIndex.value]
	if (currentInfo.value) {
		popData.value[0].value = currentInfo.value._id
		popData.value[1].value = currentInfo.value.nickname
		popData.value[2].value = currentInfo.value.score + '分'
		popData.value[3].value = currentInfo.value.description
		popData.value[4].tabs = currentInfo.value.tabs
	}
	readImgFun()
})

const swiperChange = (e) => {
	currentIndex.value = e.detail.current
	currentInfo.value = classList.value[currentIndex.value]
	if (currentInfo.value) {
		popData.value[0].value = currentInfo.value._id
		popData.value[1].value = currentInfo.value.nickname
		popData.value[2].value = currentInfo.value.score + '分'
		popData.value[3].value = currentInfo.value.description
		popData.value[4].tabs = currentInfo.value.tabs
	}
	readImgFun()
}

如下代码我们设置完相关数据之后,最终呈现的效果如下所示:

评分操作:接下来我们开始对评分操作,当然页面默认的评分我们是从接口中进行获取,这里我们先把默认的接口的评分数据进行页面的渲染,如下所示:

处理评分的操作如下所示:

// 处理提交分数
const submitScore = async () => {
	uni.showLoading({
		title: "加载中..."
	})
	let { classid, _id: wallId } = currentInfo.value
	let res = await apiSetupScore({
		classid,
		wallId,
		userScore: userScore.value
	})
	uni.hideLoading()
	if (res.errCode === 0) {
		uni.showToast({
			title: "评分成功",
			icon: "none"
		})
		classList.value[currentIndex.value].userScore = userScore.value
		uni.setStorageSync("storgClassList", classList.value)
		handleScoreClose()
	}
}

最终呈现的效果如下所示:

接下来我们开始处理下载的功能操作,这里我们使用到uni提供的api进行操作,如下所示:

代码如下所示:

这里注意要使用合法的下载域名白名单:

当然这里的用户协议也要更新一下处理:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务注册中心都有哪些

在微服务架构中&#xff0c;注册中心扮演着至关重要的角色&#xff0c;用于服务的注册与发现。以下是一些常见的注册中心&#xff1a; Eureka&#xff1a; Eureka是Netflix开发的服务发现框架&#xff0c;后来贡献给了Spring Cloud。它主要用于AWS云&#xff0c;但也可以在其他…

【MySQL超详细安装步骤】Centos7安装MySQL8

文章目录 1.卸载2.修改yum源为阿里源2.1首先检查是否安装wget2.2 备份 yum 源文件2.3 下载阿里云yum源文件2.4 清理yum缓存 3.安装mysql源3.1 下载mysql源3.2 安装mysql源3.3 检查是否安装成功 4. 安装MySQL4.1 使用yum安装4.2 启动MySQL 5.配置防火墙5.1 开放3306端口 6.登录M…

服务器数据恢复—Raid磁盘阵列故障类型和常见故障原因

出于尽可能避免数据灾难的设计初衷&#xff0c;RAID解决了3个问题&#xff1a;容量问题、IO性能问题、存储安全(冗余)问题。从数据恢复的角度讨论RAID的存储安全问题。 常见的起到存储安全作用的RAID方案有RAID1、RAID5及其变形。基本设计思路是相似的&#xff1a;当部分数据异…

go切片的深入学习以及context库的使用

Go切片专项学习 go切片扩容机制 go1.18 之前&#xff1a; 1.如果期望容量大于当前容量的两倍就会使用期望容量&#xff1b; 2.如果当前切片的长度小于 1024 就会将容量翻倍&#xff1b; 3.如果当前切片的长度大于 1024 就会每次增加 25% 的容量&#xff0c;直到新容量大于期…

JavaScript - 对象编程之详解DOM对象

1. 文档对象模型&#xff08;DOM&#xff09; HTML DOM全称为HTML Document Object Model&#xff0c;专门适用于HTML/XHTML文档的对象模型。可以将HTML DOM理解为网页的API&#xff0c;将网页中的各种元素都看作一个对象&#xff0c;从而使网页中的元素也可以被计算机语言获取…

git的简单学习

&#xff08;这个模块本来是会用的&#xff0c;但是了解并不是那么深入&#xff0c;因此需要继续学习一下&#xff09; 1.下载安装 下载网址&#xff1a;https://git-scm.com/download/win/ 一直next就可以了。 2.检查 winr&#xff1a;cmd &#xff08;不建议&#xff09;…

零基础Opencv学习(四)

一、查找并绘制轮廓 /// 载入原始图&#xff0c;必须以二值图模式载入cv::Mat image cv::imread("E:/OpencvStudyTest/4.png", cv::ImreadModes::IMREAD_GRAYSCALE);cv::imshow("image", image);/// 初始化结果图cv::Mat dstImage cv::Mat::zeros(image.…

005:VTK世界坐标系中的相机和物体

VTK医学图像处理---世界坐标系中的相机和物体 左侧是成像结果 右侧是世界坐标系中的相机与被观察物体 简介 上图右侧的图像是模拟的世界坐标系和世界坐标系中相机以及被观察物体&#xff1b; 左侧是在右侧世界坐标系中相机…

黑神话:游戏的诞生

&#x1f6f0; 前言 近期&#xff0c;国产 3A 大作《黑神话&#xff1a;悟空》给我们带来了一波惊喜。相信各位或多或少都有所了解。看见如此激动人心的产品我们除了欣喜&#xff0c;也不禁让我们思考起来游戏是如何实现的&#xff1f;我们能否开发一款属于自己的游戏&#xff…

3D 场景模拟 2D 碰撞玩法的方案

目录 方法概述顶点到平面的垂直投影求解最小降维 OBB主成分分析&#xff08;PCA&#xff09;协方差矩阵求矩阵特征值Jacobi 方法 OBB 拉伸方法 对于类似《密特罗德 生存恐惧》和《暗影火炬城》这样 3D 场景&#xff0c;但玩法还是 2D 卷轴动作平台跳跃&#xff08;类银河恶魔城…

[项目][CMP][Central Cache]详细讲解

目录 1.设计&结构2.申请内存3.释放内存4.框架 1.设计&结构 Central Cache也是一个哈希桶结构&#xff0c;它的哈希桶的映射关系跟Thread Cache是一样的不同的是它的每个哈希桶位置挂的是SpanList链表结构(带头双向循环链表)&#xff0c;不过每个映射桶下面的span中的大…

链式栈、队列

1、链式栈&#xff1a; 声明&#xff1a; #ifndef _STACK_H #define _STACK_H #include<stdlib.h>typedef int DataType;typedef struct snode //节点 {DataType data;struct snode *pnext; }SNode_t;typedef struct stack //链表 {SNode_t *ptop;int clen; }St…

Patlibc———更快捷的更换libc

起初是为了简化做pwn题目时&#xff0c;来回更换libc的麻烦&#xff0c;为了简化命令&#xff0c;弄了一个小脚本&#xff0c;可以加入到/usr/local/bin中&#xff0c;当作一个快捷指令&#x1f522; 这个写在了tools库&#xff08;git clone https://github.com/CH13hh/tools…

C++利用jsoncpp库实现写入和读取json文件(含中文处理)

C利用jsoncpp库实现写入和读取json文件 1 jsoncpp常用类1.1 Json::Value1.2 Json::Reader1.3 Json::Writer 2 json文件3 写json文件3.1 linux存储结果3.2 windows存储结果 3 读json文件4 读json字符串参考文章 在C中使用跨平台的开源库JsonCpp&#xff0c;实现json的序列化和反…

【有啥问啥】大模型应用中的哈希链推理任务

大模型应用中的哈希链推理任务 随着人工智能技术的快速发展&#xff0c;尤其是大模型&#xff08;如GPT、BERT、Vision Transformer等&#xff09;的广泛应用&#xff0c;确保数据处理和模型推理的透明性与安全性变得愈发重要。哈希链推理任务作为一种技术手段&#xff0c;能够…

会员营销如何利用JSON发送短信

在当今这个数字化时代&#xff0c;企业间的竞争日益激烈&#xff0c;如何高效地触达并维护用户群体&#xff0c;提升用户粘性和忠诚度&#xff0c;成为了每个企业都必须面对的重要课题。在众多营销手段中&#xff0c;会员营销因其精准性和个性化而备受青睐。而在会员营销的策略…

人工智能导论(上)

一、人工智能概述 人工智能这个基本概念的起源&#xff08;人工智能作为计算机科学的一个分支&#xff09; 很多应用研究领域都在人工智能的范畴里&#xff0c;比如机器人、语言识别、图像识别、自然语言处理和专家系统等等。更加通俗的说&#xff0c;人工智能是要让一部机器能…

传输层协议UDP

本篇将主要介绍 UDP 协议&#xff0c;介绍了有关 UDP 协议的报头、协议特点、UDP 协议在操作系统中的缓冲区、UDP 协议使用的注意事项&#xff0c;以及有关 UDP 的 Socket 编程程序&#xff0c;同时重点介绍了操作系统对于 UDP 协议报文的管理。 接着介绍了有关端口号的映射。 …

s3c2440---中断控制器

一、概述 S3C2440A 中的中断控制器接受来自 60 个中断源的请求。提供这些中断源的是内部外设&#xff0c;如 DMA 控制器、 UART、IIC 等等。 在这些中断源中&#xff0c;UARTn、AC97 和 EINTn 中断对于中断控制器而言是“或”关系。 当从内部外设和外部中断请求引脚收到多个中…

哲学概述2(马克)

三、哲学的基本问题 思维是主观的&#xff08;对应意识&#xff09; 存在是客观的&#xff0c;不以人的意志为转移&#xff08;对应物质&#xff09; 恩格斯说&#xff1a;“全部哲学&#xff0c;特别是近代哲学的重大的基本问题&#xff0c;是思维和存在的关系问题” 哲学的基…