当前位置: 首页 > news >正文

HarmonyOS5 购物商城app(二):购物车与支付(附代码)

鸿蒙应用购物车模块开发实践:从代码解析到功能实现

一、引言

在鸿蒙(HarmonyOS)应用生态中,购物车功能是电商类应用的核心组成部分,它承担着整合用户选购商品、计算总价、支撑支付流程等关键职责。本文将深入剖析一段鸿蒙应用购物车功能的实现代码,详细解读从商品数据管理、界面交互到支付流程衔接的完整逻辑,为鸿蒙应用开发者提供实践参考。

二、数据模型搭建:构建购物车基石

(一)商品类 ShopClass 定义

class ShopClass {img: string = ''name: string = ''attributes: string = ''price: number = 0id: number = 0quantity: number = 0constructor(img: string, name: string, attributes: string, price: number, id: number, quantity: number) {this.img = imgthis.name = namethis.attributes = attributesthis.price = pricethis.id = idthis.quantity = quantity}
}

ShopClass 作为购物车商品的数据载体,清晰定义了商品图片路径、名称、属性描述、价格、唯一标识及数量等核心属性 。通过构造函数,能便捷地初始化商品信息,为后续购物车功能实现提供基础数据模型,让每个商品在购物车流程中都有明确的“身份”与“特征”。

(二)支付信息接口 pays 设计

interface pays{pay: numbershopDel: Array<ShopClass>
}

pays 接口用于规范购物车结算时传递的支付相关数据结构,其中 pay 存储结算总金额,shopDel 存放已选中待支付的商品集合,确保购物车页面与支付页面间数据传递的准确性与规范性,是衔接购物车结算和支付流程的关键数据桥梁。

三、主页面 Index:购物车核心交互载体

(一)状态与数据管理

@Entry
@Component
struct Index {@Provide  ('shopArray') ShopArray: Array<ShopClass> = [new ShopClass('app.media.shop_01', '华为家居小户科技布', '蓝色 尺寸L', 3600, 1, 1),new ShopClass('app.media.shop_02', '简约现代餐桌椅组合', '白色 一套', 8999, 2, 1),new ShopClass('app.media.shop_03', '智能无线吸尘器', '星空灰', 1499, 3, 1)]@State ShopDel: Array<ShopClass> = []@State flag: boolean = false@State priceSum: number = 0@Provide('mainStarIndex') mainStarIndex: NavPathStack = new NavPathStack();//...
}
  • @Provide@State 装饰器@Provide('shopArray') 共享商品列表数据,方便子组件访问;@State 分别管理已选中商品集合 ShopDel、全选状态 flag 以及总价 priceSum ,实现组件内部状态的响应式更新。
  • NavPathStack:借助其实现页面导航功能,搭建购物车主页与支付页的跳转逻辑,让用户在购物流程中能顺畅切换页面。

(二)界面构建与交互逻辑

1. 标题栏设计
Row() {Row({ space: 10 }) {Image($r('app.media.shopcar')) .width(50).height(50)Text('购物车').fontSize(24).fontWeight(FontWeight.Bold)}.width('100%').justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).padding({ top: 10, bottom: 15 })
}

通过 Row 组件搭建购物车标题栏,整合购物车图标与标题文本。设置布局属性,让标题栏在界面上美观且布局合理,为用户提供清晰的功能入口标识。

2. 商品列表展示
Scroll() {Column() {List() {ForEach(this.ShopArray, (item: ShopClass, index) => {ListItem() {shops({item: item,ShopDel: this.ShopDel,priceSum: this.priceSum,ShopArray: this.ShopArray})}.margin({ top: 10 })})}.lanes(1, 10)}.height('100%').justifyContent(FlexAlign.Start).backgroundColor('#fff5f5f5')
}
.layoutWeight(1)
.width('100%')
.padding(10)

利用 ScrollListForEach 等组件构建商品滚动列表。shops 子组件负责渲染单个商品条目,实现商品展示、选中状态切换及数量调整等交互功能,让用户能直观浏览和操作购物车中的商品。

3. 结算栏交互
Row({ space: 8 }) {Checkbox().onChange((val) => {this.flag = valif (val) {this.ShopArray.forEach((item) => {if (!this.ShopDel.some(delItem => delItem.id === item.id)) {this.ShopDel.push(item);}})} else {this.ShopDel = []}this.updateTotalPrice()})Text('全选').layoutWeight(1)Text('合计:')Text(`¥${this.priceSum}`)Button('结算').backgroundColor(Color.Orange).onClick(() => {const pay:pays = { pay: this.priceSum, shopDel: this.ShopDel }this.mainStarIndex.pushPathByName('pay', pay)})
}
.height(60)
.width('100%')
.padding(16)
  • 全选功能:复选框 Checkbox 结合 onChange 事件,实现全选或取消全选逻辑。全选时遍历商品列表,将未选中商品加入 ShopDel;取消全选则清空 ShopDel,并调用 updateTotalPrice 更新总价。
  • 结算流程:结算按钮点击时,构建支付数据 pays,通过 NavPathStackpushPathByName 方法跳转至支付页面,开启支付流程。

四、商品条目 shops 组件:精细化商品交互

@Reusable
@Component
struct shops {@Prop item: ShopClass@Link ShopDel: Array<ShopClass>@Link priceSum: number@Link ShopArray: Array<ShopClass>@State checkboxif: boolean = false build() {Row({ space: 10 }) {Checkbox().onChange((value) => {if (value) {if (!this.ShopDel.some(delItem => delItem.id === this.item.id)) {this.checkboxif = truethis.ShopDel.push(this.item);}} else {this.ShopDel = this.ShopDel.filter((delItem) => delItem.id !== this.item.id);this.checkboxif = false}this.updateTotalPrice()this.checkboxif = this.ShopDel.length === this.ShopArray.length}).width(20)// 商品图片、信息列、数量控制区域等构建逻辑}.width('100%').height(80).backgroundColor(Color.White).borderRadius(8) .shadow({ color: '#1de9b6', radius: 4 }) }updateTotalPrice(): void {let total = 0this.ShopDel.forEach((shopItem) => {total += shopItem.price * shopItem.quantity})this.priceSum = total}
}
  • 交互逻辑:作为商品列表子组件,通过 @Prop@Link 接收数据并实现双向绑定。复选框实现商品选中/取消选中功能,同步更新 ShopDel、总价及全选状态;数量控制区域的 “-”“+” 按钮,调整商品数量并实时更新总价,让用户能精细化操作单个商品。
  • 界面美化:设置组件背景色、圆角及阴影效果,提升商品条目的视觉呈现,优化用户体验。

五、支付页面 pay 组件:完成购物闭环

@Component
struct pay {@Consume('mainStarIndex') mainStarIndex: NavPathStack;@Consume  ('shopArray') shopArray: Array<ShopClass>@Prop pay: paysbuild() {NavDestination(){Column() {// 金额展示、支付方式选择、按钮等构建逻辑}.width('100%').height('100%').justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Center)}}onClickPay() {AlertDialog.show({message: '是否支付!',buttons: [{value: '确定',action: () => {this.shopArray = this.shopArray.filter((item) => !this.pay.shopDel.some(delItem => delItem.id === item.id))this.mainStarIndex.pop(); prompt.showToast({ message: '支付成功!' });}},{value: '取消',action: () => {}}]});}
}
  • 支付流程:接收支付数据与商品列表,展示支付金额及支付宝、微信等支付方式选项。确认支付按钮点击后,弹出对话框询问用户,确认则从商品列表移除已结算商品,通过 mainStarIndex.pop() 返回购物车主页并提示支付成功;取消则终止支付流程,完成购物闭环的最后一环。
  • 用户反馈:利用 prompt.showToast 提供支付结果反馈,增强用户对操作的感知。

六、附:代码

import { prompt } from '@kit.ArkUI'// 商品类定义
class ShopClass {img: string = ''name: string = ''attributes: string = ''price: number = 0id: number = 0quantity: number = 0constructor(img: string, name: string, attributes: string, price: number, id: number, quantity: number) {this.img = imgthis.name = namethis.attributes = attributesthis.price = pricethis.id = idthis.quantity = quantity}
}
interface pays{pay: numbershopDel: Array<ShopClass>
}@Entry
@Component
struct Index {// 购物车商品列表数据源@Provide  ('shopArray') ShopArray: Array<ShopClass> = [new ShopClass('app.media.shop_01', '华为家居小户科技布', '蓝色 尺寸L', 3600, 1, 1),new ShopClass('app.media.shop_02', '简约现代餐桌椅组合', '白色 一套', 8999, 2, 1),new ShopClass('app.media.shop_03', '智能无线吸尘器', '星空灰', 1499, 3, 1)]// 已选中商品集合@State ShopDel: Array<ShopClass> = []// 全选状态标志@State flag: boolean = false// 总价@State priceSum: number = 0@Provide('mainStarIndex') mainStarIndex: NavPathStack = new NavPathStack();@BuildershopPage(name: string, params: pays) {if (name === 'pay') {pay({pay:  params,})}}build() {Navigation(this.mainStarIndex){Column() {// 购物车标题栏Row() {Row({ space: 10 }) {Image($r('app.media.shopcar')) // 使用合适的购物车图标资源.width(50).height(50)Text('购物车').fontSize(24).fontWeight(FontWeight.Bold)}.width('100%').justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).padding({ top: 10, bottom: 15 })}Divider()// 商品滚动列表Scroll() {Column() {// 商品列表容器List() {ForEach(this.ShopArray, (item: ShopClass, index) => {ListItem() {shops({item: item,ShopDel: this.ShopDel,priceSum: this.priceSum,ShopArray: this.ShopArray})}.margin({ top: 10 })})}.lanes(1, 10)}.height('100%').justifyContent(FlexAlign.Start).backgroundColor('#fff5f5f5')}.layoutWeight(1).width('100%').padding(10)Divider()// 结算栏Row({ space: 8 }) {Checkbox().onChange((val) => {// 全选/取消全选逻辑this.flag = valif (val) {this.ShopArray.forEach((item) => {if (!this.ShopDel.some(delItem => delItem.id === item.id)) {this.ShopDel.push(item);}})} else {// 取消全选时清空ShopDelthis.ShopDel = []}// 更新总价this.updateTotalPrice()})Text('全选').layoutWeight(1)// 计算总价Text('合计:')Text(`¥${this.priceSum}`)Button('结算').backgroundColor(Color.Orange).onClick(() => {// 模拟结算操作const pay:pays = { pay: this.priceSum, shopDel: this.ShopDel }this.mainStarIndex.pushPathByName('pay', pay)})}.height(60).width('100%').padding(16)}.width('100%').height('100%')}.hideTitleBar(true).mode(NavigationMode.Stack).navDestination(this.shopPage)}// 单独提取更新总价的函数,便于维护和调用updateTotalPrice(): void {this.priceSum = this.ShopDel.reduce((sum, item) => sum + item.price * item.quantity, 0)}
}// 商品项构建器
@Reusable
@Component
struct shops {@Prop item: ShopClass@Link ShopDel: Array<ShopClass>@Link priceSum: number@Link ShopArray: Array<ShopClass>@State checkboxif: boolean = false // shop状态build() {Row({ space: 10 }) {// 复选框 - 用于选择商品Checkbox().onChange((value) => {if (value) {// 如果 value 为 true,将 item 添加到 this.ShopDel 中if (!this.ShopDel.some(delItem => delItem.id === this.item.id)) {this.checkboxif = truethis.ShopDel.push(this.item);}} else {// 如果 value 为 false,从 this.ShopDel 中移除当前的 itemthis.ShopDel = this.ShopDel.filter((delItem) => delItem.id !== this.item.id);this.checkboxif = false}// 更新总价this.updateTotalPrice()// 更新全选状态this.checkboxif = this.ShopDel.length === this.ShopArray.length}).width(20)// 商品图片Image($r(this.item.img)).width(80)// 商品信息列Column() {// 商品名称Text(this.item.name).width('100%').maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })// 商品属性Text(this.item.attributes).width('100%')// 商品价格Text(`¥${this.item.price}`).width('100%').fontColor('#ff527fb') // 修正颜色值格式}.width(100)// 数量控制区域Column({ space: 5 }) {Text('数量:').fontSize(12).textAlign(TextAlign.Center)Row({ space: 5 }) {Text('-').width(25).height(25).onClick(() => {if (this.item.quantity > 1) {this.item.quantity--this.updateTotalPrice()}})Text(`${this.item.quantity}`).width(25).textAlign(TextAlign.Center)Text('+').width(25).height(25).onClick(() => {this.item.quantity++this.updateTotalPrice()})}.justifyContent(FlexAlign.SpaceAround)}.width(80)// 详情箭头图标Image($r('app.media.black')).width(10).onClick(() => {// TODO 模拟跳转详情页})}.width('100%').height(80).backgroundColor(Color.White).borderRadius(8) // 添加圆角效果.shadow({ color: '#1de9b6', radius: 4 }) // 添加阴影效果}// 提取公共方法来更新总价updateTotalPrice(): void {let total = 0this.ShopDel.forEach((shopItem) => {total += shopItem.price * shopItem.quantity})this.priceSum = total}
}@Component
struct pay {@Consume('mainStarIndex') mainStarIndex: NavPathStack;@Consume  ('shopArray') shopArray: Array<ShopClass>@Prop pay: paysbuild() {NavDestination(){Column() {Row(){Text('合计:').fontSize(30).fontWeight(FontWeight.Bold)Text(`¥${this.pay.pay}`).fontSize(30).fontWeight(FontWeight.Bold)}// 支付方式标题Text('选择支付方式').fontSize(20).fontWeight(FontWeight.Bold).padding({ top: 20, bottom: 10 })Divider()// 支付宝支付选项Row({ space: 15 }) {Image($r('app.media.alipay')) // 假设已有支付宝图标资源.width(30).height(30)Text('支付宝').fontSize(16)Checkbox().onChange((value) => {if (value) {// 可以添加相关逻辑,如记录用户选择了支付宝支付console.log("用户选择了支付宝支付")}})}.width('90%').padding({ left: 20, right: 20 }).justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).margin({ top: 10 })Divider()// 微信支付选项Row({ space: 15 }) {Image($r('app.media.wechatpay')) // 假设已有微信支付图标资源.width(30).height(30)Text('微信').fontSize(16)Checkbox().onChange((value) => {if (value) {// 可以添加相关逻辑,如记录用户选择了微信支付console.log("用户选择了微信支付")}})}.width('90%').padding({ left: 20, right: 20 }).justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).margin({ top: 10 })Divider()// 提交支付按钮Button('确认支付').onClick(() => {// 跳转·到支付页面this.onClickPay()}).backgroundColor(Color.Orange).width('80%').margin({ top: 30 })}.width('100%').height('100%').justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Center)}}// 支付点击事件处理函数onClickPay() {// 模拟支付成功提示AlertDialog.show({message: '是否支付!',buttons: [{value: '确定',action: () => {// 移除已选商品并返回首页// this.pay.ShopDel = this.ShopDel.filter((delItem) => delItem.id !== item.id);this.shopArray = this.shopArray.filter((item) => !this.pay.shopDel.some(delItem => delItem.id === item.id));this.mainStarIndex.pop(); // 返回首页// 提示支付成功prompt.showToast({ message: '支付成功!' });}},{value: '取消',action: () => {// 取消支付操作}}]});}
}

相关文章:

  • 使用DevEco Testing快速创建HarmonyOS5单元测试
  • 从源码角度了解Elasticsaerch(分布式协调排序、深分页问题)
  • 【Java】脱离 JVM 约束 GraalVM + Liberica NIK + Spring + Docker 将 Java 编译为平台二进制可执行文件
  • 亚马逊深度整合全食超市,重塑全球跨境电商与生鲜零售格局
  • FPGA基础 -- Verilog语言要素之值集合
  • CentOS7安装MySQL8.0.42
  • 展开说说Android之Retrofit详解_使用篇
  • 深度解析MySQL中的Join算法:原理、实现与优化
  • 如何在 Windows 上打造 macOS 式快速查看体验?
  • 2025最新1000+道Java面试题+答案整理(附JVM/MySQL/Spring/Redis)
  • 136.在 Vue3 中使用 OpenLayers 实现 GroupLayer 的添加、删除、显示、隐藏
  • P2C (Point-to-Curve) 算法深度解析
  • 传统的提示词优化中,损失函数有哪些
  • iOS即时通讯发送图片消息内存暴涨优化
  • 10.C S编程错误分析
  • MySQL 自增主键 ID 设置为 0有坑
  • 二叉树的最大深度题解
  • Apache Kafka Connect任意文件读取漏洞(CVE-2025-27817)
  • AWS Config:概述、优势以及如何开始?
  • Jmeter的三种参数化方式详解
  • 医院导航网站怎么做/百度互联网营销顾问
  • 什么网站的易用性/东莞seo建站优化哪里好
  • 制作logo免费网站/360网站推广
  • 外管局网站做延期收汇报告/网站用户体验优化
  • 易居做网站/今天上海最新新闻事件
  • 网站建设氺首选金手指13/怎么自己制作网站