如何使用ArkUI从0-1写一个开发购物应用程序(下)

news/2025/3/15 5:12:40/

接下来我们继续学习如何用ArkUI来开发一个购物应用程序(下半部分)

底部组件是由一个横向的图片列表组成,iconPath是底部初始状态下的3张图片路径数组。遍历iconPath数组,使用Image组件设置图片路径并添加到List中,给每个Image组件设置点击事件,点击更换底部3张图片。在HomeBottom中,iconPath使用的是@State修饰,当iconPath数组内容变化时,页面组件有使用到的地方都会随之发生变化。

在MyPage.ets文件中新建MyTransList组件和MoreGrid组件,MyTransList组件代码如下:

@Component
struct MyTransList {private imageItems: ImageItem[] = getTrans()build() {Column() {Text('My Transaction').fontSize(20).margin({ left: 10 }).width('100%').height(30)Row() {List() {ForEach(this.imageItems, item => {ListItem() {DataItem({ imageItem: item })}}, item => item.id.toString())}.height(70).width('100%').align(Alignment.Top).margin({ top: 5}).listDirection(Axis.Horizontal)}}.height(120)}
}

MoreGrid组件代码如下:

@Component
struct MoreGrid {private gridRowTemplate: string = ''private imageItems: ImageItem[] = getMore()private heightValue: numberaboutToAppear() {var rows = Math.round(this.imageItems.length / 3);this.gridRowTemplate = '1fr '.repeat(rows);this.heightValue = rows * 75 ;}build() {Column() {Text('More').fontSize(20).margin({ left: 10 }).width('100%').height(30)Scroll() {Grid() {ForEach(this.imageItems, (item: ImageItem) => {GridItem() {DataItem({ imageItem: item })}}, (item: ImageItem) => item.id.toString())}.rowsTemplate(this.gridRowTemplate).columnsTemplate('1fr 1fr 1fr').columnsGap(8).rowsGap(8).height(this.heightValue)}.padding({ left: 16, right: 16 })}.height(400)}
}

在MyTransList和MoreGrid组件中都包含子组件DataItem,为避免的重复代码,可以把多次要用到的结构体组件化,这里的结构体就是图片加上文本的上下结构体,DataItem组件内容如下:

@Component
struct MenuItem {private menu: Menubuild() {Column() {Text(this.menu.title).fontSize(15)Text(this.menu.num+'').fontSize(13)}.height(50).width(80).margin({left: 8,right:8}).alignItems(HorizontalAlign.Start).backgroundColor(Color.White)}
}

实现购物车页签

主界面购物车页签主要由下面三部分组成:

  • 顶部的Text组件。
  • 中间的List组件,其中List组件的item是一个水平的布局内包含一个toggle组件,一个Image组件和一个垂直布局,其item中的垂直布局是由2个Text组件组成。
  • 底部一个水平布局包含两个Text组件。

构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部Total值也会随之增加或减少,点击Check Out时会触发弹窗。下面我们来完成ShoppingCart页签。

在pages目录下面新建一个Page ,命名为ShoppingCart.。在ShoppingCart.ets文件中添加入口组件(ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart组件代码如下:

@Entry
@Component
export struct ShoppingCart {@Provide totalPrice : number =0private goodsItems: GoodsData[] = initializeOnStartup()build() {Column() {Column() {Text('ShoppingCart').fontColor(Color.Black).fontSize(25).margin({ left: 60,right:60 }).align(Alignment.Center)}.backgroundColor('#FF00BFFF').width('100%').height(30)ShopCartList({ goodsItems: this.goodsItems });ShopCartBottom()}.alignItems(HorizontalAlign.Start)}
}

新建ShopCartList组件用于存放购物车商品列表,ShopCartList组件代码如下

@Component
struct ShopCartList {private goodsItems: GoodsData[]build() {Column() {List() {ForEach(this.goodsItems, item => {ListItem() {ShopCartListItem({ goodsItem: item })}}, item => item.id.toString())}.height('100%').width('100%').align(Alignment.Top).margin({top: 5})}.height(570)}
}

ShopCartListItem组件代码如下:

@Component
struct ShopCartListItem {@Consume totalPrice: numberprivate goodsItem: GoodsDatabuild() {Row() {Toggle({type: ToggleType.Checkbox}).width(10).height(10).onChange((isOn:boolean) => {if(isOn){this.totalPrice +=parseInt(this.goodsItem.price+'',0)}else{this.totalPrice -= parseInt(this.goodsItem.price+'',0)}})Image(this.goodsItem.imgSrc).objectFit(ImageFit.ScaleDown).height(100).width(100).renderMode(ImageRenderMode.Original)Column() {Text(this.goodsItem.title).fontSize(14)Text('¥' + this.goodsItem.price).fontSize(14).fontColor(Color.Red)}}.height(100).width(180).margin({left: 20}).alignItems(VerticalAlign.Center).backgroundColor(Color.White)}
}

在ShopCartListItem中使用Toggle的单选框类型来实现每个item的选择和取消选择,在Toggle的onChage事件中来改变totalPrice的数值。

新建ShopCartBottom组件,ShopCartBottom组件代码如下:

@Component
struct ShopCartBottom {@Consume totalPrice: numberbuild() {Row() {Text('Total:  ¥'+this.totalPrice).fontColor(Color.Red).fontSize(18).margin({left:20}).width(150)Text('Check Out').fontColor(Color.Black).fontSize(18).margin({right:20,left:100}).onClick(()=>{prompt.showToast({message: 'Checking Out',duration: 10,bottom:100})})}.height(30).width('100%').backgroundColor('#FF7FFFD4').alignItems(VerticalAlign.Bottom)}
}

实现我的页签

我的页签主要由下面四部分组成:

  • 顶部的水平布局。
  • 顶部下面的文本加数字的水平List。
  • My Transactio模块,图片加文本的水平List。
  • More模块,图片加文本的Grid。

构建主页我的页签,主要可以划分成下面几步:

  • 在pages目录下面新建一个Page 命名为MyPage
  • 在MyPage.ets文件中添加入口组件(MyInfo)

MyInfo组件内容如下:

import {getMenu,getTrans,getMore} from '../model/GoodsDataModels'
import {Menu, ImageItem} from '../model/Menu'
@Entry
@Component
export struct MyInfo {build() {Column() {Row(){Image($rawfile('nav/icon-user.png')).margin({left:20}).objectFit(ImageFit.Cover).height(50).width(50).renderMode(ImageRenderMode.Original).margin({left:40,right:40})Column(){Text('John Doe').fontSize(15)Text('Member Name : John Doe                     >')}.height(60).margin({left:40,top:10}).alignItems(HorizontalAlign.Start)}TopList()MyTransList()MoreGrid()}.alignItems(HorizontalAlign.Start).width('100%').flexGrow(1)}
}

入口组件中还包含TopList,MyTransList和MoreGrid三个子组件。代码如下:

@Component
struct TopList {private menus: Menu[] = getMenu()build() {Row() {List() {ForEach(this.menus, item => {ListItem() {MenuItem({ menu: item })}}, item => item.id.toString())}.height('100%').width('100%').margin({top: 5}).edgeEffect(EdgeEffect.None).listDirection(Axis.Horizontal)}.width('100%').height(50)}
}
@Component
struct MyTransList {private imageItems: ImageItem[] = getTrans()build() {Column() {Text('My Transaction').fontSize(20).margin({ left: 10 }).width('100%').height(30)Row() {List() {ForEach(this.imageItems, item => {ListItem() {DataItem({ imageItem: item })}}, item => item.id.toString())}.height(70).width('100%').align(Alignment.Top).margin({ top: 5}).listDirection(Axis.Horizontal)}}.height(120)}
}
@Component
struct MoreGrid {private gridRowTemplate: string = ''private imageItems: ImageItem[] = getMore()private heightValue: numberaboutToAppear() {var rows = Math.round(this.imageItems.length / 3);this.gridRowTemplate = '1fr '.repeat(rows);this.heightValue = rows * 75 ;}build() {Column() {Text('More').fontSize(20).margin({ left: 10 }).width('100%').height(30)Scroll() {Grid() {ForEach(this.imageItems, (item: ImageItem) => {GridItem() {DataItem({ imageItem: item })}}, (item: ImageItem) => item.id.toString())}.rowsTemplate(this.gridRowTemplate).columnsTemplate('1fr 1fr 1fr').columnsGap(8).rowsGap(8).height(this.heightValue)}.padding({ left: 16, right: 16 })}.height(400)}
}

实现商品详情页面

商品详情页面主要由下面五部分组成:

  • 顶部的返回栏。
  • Swiper组件。
  • 中间多个Text组件组成的布局。
  • 参数列表。
  • 底部的Buy。

把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部Buy时,会触发进度条弹窗。

在pages目录下面新建一个Page, 命名为ShoppingDetail。在ShoppingDetail.ets文件中创建入口组件,组件内容如下:

import router from '@system.router';
import {ArsData} from '../model/ArsData'
import {getArs,getDetailImages} from '../model/GoodsDataModels'
import prompt from '@system.prompt';
@Entry
@Component
struct ShoppingDetail {private arsItems: ArsData[] =  getArs()private detailImages: string[] = getDetailImages()build() {Column() {DetailTop()Scroll() {Column() {SwiperTop()DetailText()DetailArsList({ arsItems: this.arsItems })Image($rawfile('computer/computer1.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer2.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer3.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer4.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer5.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer6.png')).height(220).width('100%').margin({top:30})}.width('100%').flexGrow(1)}.scrollable(ScrollDirection.Vertical)DetailBottom()}.height(630)}
}

顶部DetailTop组件代码如下:

@Component
struct DetailTop{build(){Column(){Row(){Image($rawfile('detail/icon-return.png')).height(20).width(20).margin({ left: 20, right: 250 }).onClick(() => {router.push({uri: "pages/HomePage"})})}.width('100%').height(25).backgroundColor('#FF87CEEB')}.width('100%').height(30)}
}

SwiperTop组件代码如下:

@Component
struct SwiperTop{build() {Column() {Swiper() {Image($rawfile('computer/computer1.png')).height(220).width('100%')Image($rawfile('computer/computer2.png')).height(220).width('100%')Image($rawfile('computer/computer3.png')).height(220).width('100%')Image($rawfile('computer/computer4.png')).height(220).width('100%')Image($rawfile('computer/computer5.png')).height(220).width('100%')Image($rawfile('computer/computer6.png')).height(220).width('100%')}.index(0).autoPlay(true).interval(3000).indicator(true).loop(true).height(250).width('100%')}.height(250).width('100%')}
}

DetailText组件代码如下:

@Component
struct DetailText{build() {Column() {Row(){Image($rawfile('computer/icon-promotion.png')).height(30).width(30).margin({left:10})Text('Special Offer: ¥9999').fontColor(Color.White).fontSize(20).margin({left:10})}.width('100%').height(35).backgroundColor(Color.Red)Column(){Text('New Arrival: HUAWEI MateBook X Pro 2021').fontSize(15).margin({left:10}).alignSelf(ItemAlign.Start)Text('13.9-Inch, 11th Gen Intel® Core™ i7, 16 GB of Memory, 512 GB of Storage, Ultra-slim Business Laptop, 3K FullView Display, Multi-screen Collaboration, Emerald Green').fontSize(10).margin({left:10})Row(){Image($rawfile('nav/icon-buy.png')).height(15).width(15).margin({left:10})//TODO 暂不支持跑马灯组件,用Text代替Text('Limited offer').fontSize(10).fontColor(Color.Red).margin({left:100})}.backgroundColor(Color.Pink).width('100%').height(25).margin({top:10})Text(' Shipment:         2-day shipping').fontSize(13).fontColor(Color.Red).margin({left:10,top:5}).alignSelf(ItemAlign.Start)Text('    Ship To:         Hubei,Wuhan,China').fontSize(13).fontColor(Color.Red).margin({left:10,top:5}).alignSelf(ItemAlign.Start).onClick(()=>{prompt.showDialog({title:'select address',})})Text('Guarantee:         Genuine guaranteed').fontSize(13).margin({left:10,top:5}).alignSelf(ItemAlign.Start)}.height(150).width('100%')}.height(160).width('100%')}
}

DetailArsList组件代码如下:

@Component
struct DetailArsList{private arsItems: ArsData[]build() {Scroll() {Column() {List() {ForEach(this.arsItems, item => {ListItem() {ArsListItem({ arsItem: item })}}, item => item.id.toString())}.height('100%').width('100%').margin({ top: 5 }).listDirection(Axis.Vertical)}.height(200)}}
}

ArsListItem组件代码如下:

@Component
struct ArsListItem {private arsItem: ArsDatabuild() {Row() {Text(this.arsItem.title+" :").fontSize(11).margin({left:20}).flexGrow(1)Text( this.arsItem.content).fontSize(11).margin({right:20})}.height(14).width('100%').backgroundColor(Color.White)}
}

DetailBottom组件代码如下:

@Component
struct DetailBottom{@Provideprivate value : number=1dialogController : CustomDialogController = new CustomDialogController({builder: DialogExample({action: this.onAccept}),cancel: this.existApp,autoCancel: true});onAccept() {}existApp() {}build(){Column(){Text('Buy').width(40).height(25).fontSize(20).fontColor(Color.White).onClick(()=>{this.value=1this.dialogController.open()})}.alignItems(HorizontalAlign.Center).backgroundColor(Color.Red).width('100%').height(40)}
}

DialogExample自定义弹窗组件代码如下:

@CustomDialog
struct DialogExample {@Consumeprivate value : numbercontroller: CustomDialogController;action: () => void;build() {Column() {Progress({value: this.value++ >=100?100:this.value, total: 100, style: ProgressStyle.Eclipse}).height(50).width(100).margin({top:5})}.height(60).width(100)}
}

添加资源文件

程序中所用到的资源文件都放置到resources\rawfile目录下。

删除index.ets

因为程序的入口文件已经改为了HomePage.ets文件,因此需要删除Index.ets文件。

HomePage.ets文件重新命名

把HomePage.ets文件重新命名为Index.ets文件。

程序运行效果

以上内容是介绍了如何用ArkUI来开发一个购物应用程序全部教程

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了几套最新版的HarmonyOS NEXT学习资源

获取完整版高清学习路线,请点击→《HarmonyOS教学视频

HarmonyOS教学视频

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取白皮书:请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?《鸿蒙基础入门学习指南》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册


http://www.ppmy.cn/news/1389688.html

相关文章

VueUse常见方法使用

npm i vueuse/core 1、useDebounceFn 节流防抖 import { useDebounceFn } from vueuse/core<button type"button" class"search" click"query">查询</button>// 查询 获取table数据const query2 async () > {try {const res …

21.python——模块引用

一、语法 *import import <模块名> as <别名> *from...import... from <模块名> import <对象、函数...> 用在不同文件中引用函数 from <模块名> import * #引用该模块中所有函数

kafka集群介绍及搭建

介绍 kafka是一个高性能、低延迟、分布式的消息传递系统&#xff0c;特点在于实时处理数据。集群由多个成员节点broker组成&#xff0c;每个节点都可以独立处理消息传递和存储任务。 路由策略 发布消息由key、value组成&#xff0c;真正的消息是value&#xff0c;key是标识路…

【Java】POI解析excel

一、相关介绍 POI技术 Apache POI是Apache软件基金会的开放源码函式库&#xff0c;POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 poi-ooxml能解析xls&#xff0c;xlsx。 poi能解析word、ppt、excel、xml等office软件 导入坐标&#xff1a; <depende…

五、分支结构

一、程序的组织结构 无论程序是大是小&#xff0c;都可以用顺序结构、选择结构和循环结构表示 二、单分支结构 单分支结构&#xff1a;如果表达式的值是True就执行代码&#xff0c;如果表达式的值是False就跳过语句执行后面语句 ageint(input(请输入你的年龄&#xff1a;)) i…

圆刚广电级采集卡上市,助力直播带货产业升级

随着直播带货行业的蓬勃发展&#xff0c;市场对于高质量直播设备的需求日益增长。圆刚科技作为行业内领先的音视频方案提供商&#xff0c;近日宣布其最新产品——GC535广电级采集卡正式上市。该产品专为提升直播带货质量而设计&#xff0c;旨在解决行业面临的痛点和问题&#x…

DevEco Studio 项目创建

安装DevEco Studio后开始使用&#xff0c;双击桌面DevEco Studio 快捷方式弹出界面&#xff1a; 选择Application —> Empty Ability&#xff0c;点击Next 项目配置 Project name&#xff1a;工程的名称&#xff0c;可以自定义&#xff0c;由大小写字母、数字和下划线组成。…

基于Linux内核的socket编程(TCP)的C语言示例

原文地址&#xff1a;https://www.geeksforgeeks.org/socket-programming-cc/ 服务端&#xff1a; #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h>#…