uni-app--》基于小程序开发的电商平台项目实战(五)
🏍️作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名在校大学生
🛵个人主页:亦世凡华、
🛺系列专栏:uni-app
🚲座右铭:人生亦可燃烧,亦可腐败,我愿燃烧,耗尽所有光芒。
👀引言
⚓经过web前端的学习,相信大家对于前端开发有了一定深入的了解,今天我开设了uni-app专栏,主要想从移动端开发方向进一步发展,而对于我来说写移动端博文的第二站就是uni-app开发,希望看到我文章的朋友能对你有所帮助。
今天开始使用 vue3 + uni-app 搭建一个电商购物的小程序,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的GitHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端uni-app知识。然后开篇先简单介绍一下本项目用到的技术栈都有哪几个方面(阅读此次项目实践文章能够学习到的技术):
uni-app:跨平台的应用开发框架,基于vue.js可以一套代码同时构建运行在多个平台。
pnpm:高性能、轻量级npm替代品,帮助开发人员更加高效地处理应用程序的依赖关系。
vue3:vue.js最新版本的用于构建用户界面的渐进式JavaScript框架。
typescript:JavaScript的超集,提供了静态类型检查,使得代码更加健壮。
pinia:vue3构建的Vuex替代品,具有响应式能力,提供非常简单的 API,进行状态管理。
uni-ui:基于vue.js和uni-app的前端UI组件库,开发人员可以快速地构建跨平台应用程序。
如果是第一次接触uni-app并且想学习uni-app的朋友,我是不建议直接从此次实战项目开始看起,可以先阅读一下我以前的基础文章:什么是uniapp?如何开发uniapp?按部就班的学习可以让学习变得更轻松更容易上手哦,闲话少说我们直接开始今天的uni-app实战篇。
目录
个人中心模块搭建
设置页面的搭建
个人信息页搭建
个人信息页面数据的修改
个人中心模块搭建
在个人中心模块搭建时,这里我们打算使用自定义导航栏来设置个人模块的搭建,如果想使用自定义导航栏,我们需要在 pages.json 文件设置如下属性:

设置完自定义导航栏之后,导航栏的内容就会被组件的内容自动顶上去了,所以接下来我们就需要设置页面就可以了,在个人中心模块有两个页面需要展示,一个是登录成功的页面另一个是未登录的页面,两个页面下面都是有相应的猜你喜欢组件的相关内容,这里我们思考了一下,猜你喜欢组件的使用频率相对来说较高,所以我们把公共模块的组件代码封装成全局组件来进行公共的复用:
import { ref } from 'vue'
import type { SwGuessInstance } from '@/types/components'/*** 猜你喜欢组合式函数*/
export const useGuessList = () => {// 获取猜你喜欢组件实例const guessRef = ref<SwGuessInstance>()// 滚动触底事件const onScrolltolower = () => {guessRef.value?.getGuess()}// 返回 ref 和事件处理函数return {guessRef,onScrolltolower,}
}
个人中心模块展示不同页面的条件是根据仓库中用户信息是否存在展示的,这里需要直接调用该模块即可,通过v-if和v-else来进行相应的展示,给该滚动容器设置自定义上拉触底事件:

因为我们把自定义上拉触底事件封装成公共组件,这里直接调用即可:
const { guessRef, onScrolltolower } = useGuessList()
既然我们把猜你喜欢的公共代码模块封装成公共组件,在首页的相关猜你喜欢组件内容的模块代码也可以直接删掉换上公共代码的调用即可:

最终呈现的结果如下:

设置页面的搭建
关于设置页面一般用户不会主动去点击,这也就导致设置页面的停留次数相对较少,这里我们可以将设置页面设置一下分包,这里需要了解以下两个概念:
小程序分包:将小程序的代码分割成多个部分,分别打包成多个小程序包,减少小程序的加载时间,提高用户体验。
分包预下载:在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的加载速度。
关于分包的其他相关概念这里不再赘述,想了解更深一点的朋友可以参考我之前的文章:分包
在 vscode 中我们新建分包页面,插件已经给我们提供好了方式,只需要在相应的文件夹下鼠标右键选择新建uniapp页面(分包)即可,如下:

为了避免和主页面pages文件夹搞混淆,这里我们可以在src文件夹下重新创建一个新的文件,然后在该文件夹下再重新创建分包文件:

当我们创建分包页面的时候,相应的的在pages.json文件夹下也会生成相应的分包加载规则:

接下来我们在个人中心的设置按钮处设置相应的跳转路径:


通过如下代码来搭建设置页面的基础样式:
<template><view class="viewport"><!-- 列表1 --><view class="list" v-if="true"><navigator url="/pagesMember/address/address" hover-class="none" class="item arrow">我的收货地址</navigator></view><!-- 列表2 --><view class="list"><button hover-class="none" class="item arrow" open-type="openSetting">授权管理</button><button hover-class="none" class="item arrow" open-type="feedback">问题反馈</button><button hover-class="none" class="item arrow" open-type="contact">联系我们</button></view><!-- 列表3 --><view class="list"><navigator hover-class="none" class="item arrow" url=" ">关于小程序</navigator></view><!-- 操作按钮 --><view class="action"><view class="button">退出登录</view></view></view>
</template>
呈现的效果如下:

搭建完相关页面之后,接下来在 pages.json 文件夹下设置分包预下载规则,关于该小程序分包预下载的相关规则这里不再赘述,想了解的朋友可以直接查看官网,这里直接给出该规则:
// 分包预下载规则
"preloadRule": {"pages/my/my" :{"network": "all","packages": ["subpackage"]}
}
分包规则设置完成之后,接下来我们就可以看到,当我们访问其他页面的时候页面是正常加载的,当我们访问个人中心页面的时候,分包会自动预下载方便我们进入的分包页面:

接下我们给退出登录设置点击事件,这里我们给其相应的点击事件设置模态框提示用户退出登录的相关确定,相关代码如下:
<script setup lang="ts">
import { useMemberStore } from '@/store'const memberStore = useMemberStore()
// 退出登录
const onLogout = () => {// 模态弹窗uni.showModal({content: '是否退出登录',showCancel: true,success: (res) => {if (res.confirm) {// 清理用户信息memberStore.clearProfile()// 返回上一页uni.navigateBack()}},})
}
</script>
这里设置一下条件渲染,当用户未登录的情况下,需要将收获地址和相应的退出登录按钮进行相应的删除,代码如下:

最后呈现的结果如下:

个人信息页搭建
个人信息页是用户点击个人中心页面的用户头像或更改头像昵称跳转到个人信息页面,这里的个人信息页面也采用分包的方式,所以这里我们只需要在专门设置分包的文件夹下设置新文件profile来作为个人信息页的页面,创建页面之后在个人中心页面的相应位置设置跳转链接:

接下来编写相应的接口函数来获取个人信息数据:
// 封装个人信息数据接口
import type { ProfileDetail } from '@/types/member'
import { http } from '@/utils/http'/*** 获取个人信息*/
export const getMemberProfileAPI = () => {return http<ProfileDetail>({method: 'GET',url: '/member/profile',})
}
这里的ts类型可以将公共部分的参数分离出去,然后将独有的参数和公共的部分合并在一起:
/** 通用的用户信息 */
type BaseProfile = {/** 用户ID */id: number/** 头像 */avatar: string/** 账户名 */account: string/** 昵称 */nickname?: string
}/** 小程序登录 登录用户信息 */
export type LoginResult = BaseProfile & {/** 手机号 */mobile: string/** 登录凭证 */token: string
}/** 个人信息 用户详情信息 */
export type ProfileDetail = BaseProfile & {/** 性别 */gender?: Gender/** 生日 */birthday?: string/** 省市区 */fullLocation?: string/** 职业 */profession?: string
}
编写完相应的接口之后,接下来就需要进行引入该接口函数然后将返回的数据存储在ref数据中:
import { ref } from 'vue'
// 导入接口函数
import { getMemberProfileAPI } from '@/api/profile'
import { onLoad } from '@dcloudio/uni-app'
import type { ProfileDetail } from '@/types/member'// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
// 获取个人信息的接口
const profile = ref<ProfileDetail>()
const getMemberProfileData = async () => {const res = await getMemberProfileAPI()profile.value = res.result
}
// 页面加载时候调用
onLoad(() => {getMemberProfileData()
})
将ref数据通过插值表达式和v-bind数据绑定来动态的呈现数据,具体的页面结果如下:

个人信息页面数据的修改
修改用户头像:这里修改图片的方式我们需要借助uniapp相应的api,其相应的参数讲解这里不再赘述,想了解的可以参考相应的官方文档即可。其具体的代码如下:
// 修改头像
const onAvatarChange = () => {// 调用拍照/选择图片APIuni.chooseMedia({count: 1, // 文件个数mediaType: ['image'], // 文件类型success: (res) => {console.log(res)},})
}
结果如下:

接下来借助uniapp中的上传文件的api进行相应的操作,完整的代码如下:
// 修改头像
const onAvatarChange = () => {// 调用拍照/选择图片APIuni.chooseMedia({count: 1, // 文件个数mediaType: ['image'], // 文件类型success: (res) => {// 本地路劲const { tempFilePath } = res.tempFiles[0]// 文件上传uni.uploadFile({url: '/member/profile/avatar', // 接口地址name: 'file', // 接口参数filePath: tempFilePath, // 文件路径success: (res) => {if (res.statusCode === 200) {const avatar = JSON.parse(res.data).result.avatar// 个人信息页数据更新profile.value!.avatar = avatar// store头像更新memberStore.profile!.avatar = avataruni.showToast({ icon: 'success', title: '更新成功' })} else {uni.showToast({ icon: 'error', title: '出现错误' })}},})},})
}
最后的结果如下:

接下来开始收集相应的表单数据进行数据的更新,首先这里我们先编写相应的接口函数,如下:
/*** 修改个人信息* @param data 请求体参数*/
export const putMemberProfileAPI = (data: ProfileParams) => {return http<ProfileDetail>({method: 'PUT',url: '/member/profile',data,})
}
昵称方面的数据这里我们之间使用v-model双向数据绑定即可,使用非空断言避免其初始值不存在也就是undefined的情况,如下:

关于性别的单选框和生日方面的内容,这里直接在相应的表单中设置change函数监听其变化:

将动态改变的值存放在响应式ref数据当中:
// 修改性别
const onGenderChange: UniHelper.RadioGroupOnChange = (ev) => {profile.value.gender = ev.detail.value as Gender
}
// 修改生日
const onBirthdayChange: UniHelper.DatePickerOnChange = (ev) => {profile.value.birthday = ev.detail.value
}
选择城市方面这里也是采用相应的change事件监听其变化:

修改城市的方面需要提供两个数据,一个是前端需要的数据另一个是后端需要的数据:
// 修改城市
let fullLocationCode: [string, string, string] = ['', '', '']
const onFullLocationChange: UniHelper.RegionPickerOnChange = (ev) => {// 这是前端页面需要的详细文字数据profile.value.fullLocation = ev.detail.value.join(' ')// 这是后端需要地区编码的数据fullLocationCode = ev.detail.code!
}
最后给保存按钮设置点击函数,该函数里面调用相应的修改个人信息的接口函数,将我们收集的表单数据作为参数传递给接口函数当中:
// 点击按钮保存表单
const onSubmit = async () => {// 结构相应的数据const { nickname, gender, birthday } = profile.valueconst res = await putMemberProfileAPI({nickname,gender,birthday,provinceCode: fullLocationCode[0],cityCode: fullLocationCode[1],countyCode: fullLocationCode[2],})// 更新store昵称memberStore.profile!.nickname = res.result.nicknameuni.showToast({ icon: 'success', title: '保存成功' })setTimeout(() => {uni.navigateBack()}, 400)
}
最终呈现的结果如下:

本项目个人中心页面、个人信息页面的一些基本功能的搭建就讲解到这,下一篇文章将继续讲解项目其他页面操作,关注博主学习更多前端uni-app知识,您的支持就是博主创作的最大动力!
相关文章:
uni-app--》基于小程序开发的电商平台项目实战(五)
🏍️作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名在校大学生 🛵个人主页:亦世凡华、 🛺系列专栏:uni-app 🚲座右铭:人生亦可燃烧,亦可腐败…...
新型的终端复用器 tmux
以前遇到长时间执行任务时,一般是使用nohup加后台运行,但是涉及到少量代码编写。 同事介绍了一个screen命令,根据文档,此命令已经过时,最新的命令是tmux。 tmux的介绍文档,RedHat的这一篇非常不错。 在文…...
标准化后端向前端传来的Json数据
后端响应固定格式给前端: 1,创建一个专门存储数据的类;分别存储响应状态码code,响应数据,传输的消息。 public class CommonData {int code;Object data;String message;public CommonData(int code, String message…...
java 两个list比较,删除相同的元素
概述 在Java开发中,经常需要比较两个List并删除相同的元素。本文将介绍整个流程,并提供相应的代码示例,帮助新手开发者完成这个任务。 流程 下面是比较两个List并删除相同元素的流程: 代码示例 创建两个List 我们首先需要创建两…...
7-3 zust-sy4-10 回文诗
7-3 zust-sy4-10 回文诗 分数 10 作者 张银南 单位 浙江科技学院 回文诗是汉语特有的一种使用词序回环往复的修辞方法,正着读反着读都可以。明末浙江才女吴绛雪作《四时山水诗》,如夏景诗:香莲碧水动风凉,水动风凉夏日长。长日夏凉风动水&…...
【数据结构】排序--插入排序(希尔排序)
目录 一 基本思想 二 直接插入排序 三 希尔排序 一 基本思想 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列 。 实际中我们玩扑克牌时,就用了插入排序的思想 二…...
“探寻服务器的无限潜能:从创意项目到在线社区,你会做什么?”
文章目录 每日一句正能量前言什么是服务器?服务器能做什么?服务器怎么用?部署创意项目,还是在线社区亦或做其他的?后记 每日一句正能量 未知的下一秒,千万不要轻言放弃。 前言 在数字化时代,服…...
5年经验之谈 —— 深入了解性能测试:方法、工具和最佳实践!
性能测试是软件开发生命周期中至关重要的一部分,它有助于确保应用程序在不同负载条件下都能够高效运行。在竞争激烈的市场中,性能问题可能导致用户流失,损害声誉,并损害业务。本文将深入探讨性能测试的方法、工具和最佳实践&#…...
动态加载sprite是multiple模式(即该sprite包含了很多小图)里的小图
在Unity中,Resources.Load()方法可以用来加载资源。如果要加载Sprite下的multiple模式的图片,你需要知道这些图片的路径。 首先,你需要把你想要加载的资源放在一个名为"Resources"的文件夹内。然后,你可以使用以下代码…...
大数据 DataX 详细安装教程
目录 一、环境准备 二、安装部署 2.1 二进制安装 2.2 python 3 支持 三、Data X 初体验 3.1 配置示例 3.1.1. 生成配置模板 3.1.2 创建配置文件 3.1.3 运行 DataX 3.1.4 结果显示 3.2 动态传参 3.2.1. 动态传参的介绍 3.2.2. 动态传参的案例 3.3 迸发设置 …...
微信小程序开发之会议oa(首页搭建)
前言: 上一篇我们掌握了关于小程序的框架,这篇博客带你完成小程序版的会议OA首页。效果如下: 一, 1.1先创建OA首页页面: 首先我们先建一个新项目,在app.json中编写代码 {"pages": ["pages/…...
了解主启动类怎么运行
//SpringBootApplication 标注这个类是spring boot的应用,启动类下的所有资源都会被导入 SpringBootApplication public class SpringbootApplication { public static void main(String[] args) { //以为是启动了一个方法,没想到启动了一个服务 SpringA…...
【LeetCode】31. 下一个排列
1 问题 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&a…...
支持语音与视频即时通讯项目杂记(一)
第一部分解释服务端的实现。 (服务端结构) 下面一个用于实现TCP服务器的代码,包括消息服务器(TcpMsgServer)和文件中转服务器(TcpFileServer)。 首先,TcpServer是TcpMsgServer和Tcp…...
文档:htm格式转txt
꧂ 两个地方都保存꧁ import os import codecs from bs4 import BeautifulSoupdef generate_output_filename(file_path, save_path):# 获取文件名(不包含扩展名)file_name os.path.splitext(os.path.basename(file_path))[0]# 构造保存路径和文件名ou…...
电子邮件地址注册过程详解
许多人可能对如何注册电子邮件地址感到困惑,本文将详细解析电子邮件地址的注册过程:确定邮箱厂商、创建邮箱账户、设置电子邮件地址。 1、确定要注册的邮箱厂商 首先我们需要确定要注册哪种类型的电子邮件服务。目前市场上有许多不同的电子邮件服务提供商…...
深度学习——卷积神经网络(CNN)基础二
深度学习——卷积神经网络(CNN)基础二 文章目录 前言三、填充和步幅3.1. 填充3.2. 步幅3.3. 小结 四、多输入多输出通道4.1. 多输入通道4.2. 多输出通道4.3. 11卷积层4.4. 小结 总结 前言 上文对卷积有了初步的认识,其实卷积操作就是通过卷积…...
R语言进度条:txtProgressBar功能使用方法
R语言进度条使用攻略 在数据处理、建模或其他计算密集型任务中,我们常常会执行一些可能需要很长时间的操作。 在这些情况下,展示一个进度条可以帮助我们了解当前任务的进度,以及大约还需要多长时间来完成,R语言提供了几种简单且灵…...
Maven实战-声明周期和插件
Maven实战-声明周期和插件 Maven 设计了插件机制,每个构建步骤都可以绑定一个或者多个插件行为,而且 Maven 为大多数构建步骤编写 并绑定了默认插件。例如,针对编译的插件有 maven-compiler-plugin,针对测试的插件有 maven-sure…...
ebpf的快速开发工具--libbpf-bootstrap
基于ubuntu22.04-深入浅出 eBPF 基于ebpf的性能工具-bpftrace 基于ebpf的性能工具-bpftrace脚本语法 基于ebpf的性能工具-bpftrace实战(内存泄漏) 什么是libbpf-bootstrap libbpf-bootstrap是一个开源项目,旨在帮助开发者快速启动和开发使用eBPF(Extended Berk…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
