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

2024-09-07 07:12

本文主要是介绍uni-app--》打造个性化壁纸预览应用平台(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

🌄个人主页:亦世凡华、

🌆系列专栏: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 } = equeryParams.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.idcurrentIndex.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.idcurrentIndex.value = classList.value.findIndex(item => item._id == currentId.value)readImgFun()
})const swiperChange = (e) => {currentIndex.value = e.detail.currentreadImgFun()
}

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

🏖️预览图信息渲染

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

onLoad((e) => {currentId.value = e.idcurrentIndex.value = classList.value.findIndex(item => item._id == currentId.value)currentInfo.value = classList.value[currentIndex.value]if (currentInfo.value) {popData.value[0].value = currentInfo.value._idpopData.value[1].value = currentInfo.value.nicknamepopData.value[2].value = currentInfo.value.score + '分'popData.value[3].value = currentInfo.value.descriptionpopData.value[4].tabs = currentInfo.value.tabs}readImgFun()
})const swiperChange = (e) => {currentIndex.value = e.detail.currentcurrentInfo.value = classList.value[currentIndex.value]if (currentInfo.value) {popData.value[0].value = currentInfo.value._idpopData.value[1].value = currentInfo.value.nicknamepopData.value[2].value = currentInfo.value.score + '分'popData.value[3].value = currentInfo.value.descriptionpopData.value[4].tabs = currentInfo.value.tabs}readImgFun()
}

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

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

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

// 处理提交分数
const submitScore = async () => {uni.showLoading({title: "加载中..."})let { classid, _id: wallId } = currentInfo.valuelet 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.valueuni.setStorageSync("storgClassList", classList.value)handleScoreClose()}
}

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

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

代码如下所示:

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

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

这篇关于uni-app--》打造个性化壁纸预览应用平台(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1144408

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短