OpenHarmony 实战开发——分布式购物车案例展示~

2024-04-29 05:28

本文主要是介绍OpenHarmony 实战开发——分布式购物车案例展示~,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

分布式购物车demo 模拟的是我们购物时参加满减活动,进行拼单的场景;实现两人拼单时,其他一人添加商品到购物车,另外一人购物车列表能同步更新,且在购物车列表页面结算时,某一人结算对方也能实时知道结算金额和优惠金额。整个操作效果分为3个小动画,

  • 拉起对方用户

  • 添加商品到购物车列表

  • 购物车列表勾选

  • demo效果(HH-SCDAYU200)

工程目录

完整的项目结构目录如下

├─entry\\src\\main
│          │  config.json  应用配置文件
│          │ 
│          ├─ets
│          │  └─MainAbility
│          │      │  app.ets  ets应用程序主入口
│          │      │ 
│          │      ├─model
│          │      │      ArsData.ets     // 初始化我的页面数据
│          │      │      CommonLog.ets   // 日志类
│          │      │      GoodsData.ets   // 初始化商品信息数据类
│          │      │      MenuData.ets    // 初始化我的页面数据类
│          │      │      RemoteDeviceManager.ets  // 分布式拉起设备管理类
│          │      │      ShoppingCartDistributedData.ets  // 加入购物车分布式数据库
│          │      │      TotalSelectedDistributedData.ets // 结算购物车分布式数据库
│          │      │ 
│          │      └─pages
│          │              DetailPage.ets   // 商品详情页面
│          │              HomePage.ets     // 应用首页
│          │              MyPage.ets       // 我的页面
│          │              ShoppingCartListPage.ets  // 购物车列表页面
│     └─resources // 静态资源目录
│         ├─base
│         │  ├─element
│         │  ├─graphic
│         │  ├─layout
│         │  ├─media // 存放媒体资源
│         │  └─profile
│         └─rawfile

开发步骤

1. 新建OpenHarmony ETS项目

在DevEco Studio中点击File -> New Project ->[Standard]Empty Ability->Next,Language 选择ETS语言,最后点击Finish即创建成功。

2. 编写商品展示主页面

效果图如上可以分为两部分

2.1商品列表展示

1)首先在@entry组件入口build()中使用 Tabs作为容器,达到排行榜和推荐翻页的效果;

2)再通过 List 包裹 Row 布局依次写入 Column 包裹的三个 Text 组件和 Image 组件;

3)并通过 Navigator 组件实现点击商品跳转到商品详细页功能,页面跳转过程使用 pageTransition 转场动画

Tabs() {TabContent() {GoodsList({ goodsItems: this.goodsItems});}.tabBar("畅销榜").backgroundColor(Color.White)TabContent() {GoodsList({ goodsItems: this.goodsItems});}.tabBar("推荐").backgroundColor(Color.White)}Navigator({ target: 'pages/DetailPage' }) {Row({ space: '40lpx' }) {Column() {Text(this.goodsItem.title).fontSize('28lpx')Text(this.goodsItem.content).fontSize('20lpx')Text('¥' + this.goodsItem.price).fontSize('28lpx').fontColor(Color.Red)}.height('160lpx').width('50%').margin({ left: '20lpx' }).alignItems(HorizontalAlign.Start)Image(this.goodsItem.imgSrc).objectFit(ImageFit.ScaleDown).height('160lpx').width('40%').renderMode(ImageRenderMode.Original).margin({ right: '20lpx', left: '20lpx' })}.height('180lpx').alignItems(VerticalAlign.Center).backgroundColor(Color.White)}.params({ goodsItem: this.goodsItem ,ShoppingCartsGoods:this.ShoppingCartsGoods}).margin({ left: '40lpx' })}// 转场动画使用系统提供的多种默认效果(平移、缩放、透明度等)pageTransition() {PageTransitionEnter({ duration: 1000 }).slide(SlideEffect.Left)PageTransitionExit({ duration: 1000  }).slide(SlideEffect.Right)}
2.2底部导航栏

1)通过 Row 包裹三个 Image 组件,并添加onClick 点击事件,修改 @Consume 修饰的变量,从而改变 @Provide 装饰的变量,再通过条件渲染展示不同的页面内容;

Flex() {Image(this.iconPath[0]).objectFit(ImageFit.Cover).height('60lpx').width('60lpx').margin({left:'50lpx',right:'40lpx'}).onClick(() => {this.iconPath[0] = this.iconPathSelectsTmp[0]this.iconPath[1] = this.iconPathTmp[1]this.iconPath[2] = this.iconPathTmp[2]this.currentPage = 1})Image(this.iconPath[1]).objectFit(ImageFit.Cover).height('60lpx').width('60lpx').margin({left:'40lpx',right:'40lpx'}).onClick(() => {this.iconPath[0] = this.iconPathTmp[0]this.iconPath[1] = this.iconPathSelectsTmp[1]this.iconPath[2] = this.iconPathTmp[2]this.currentPage = 2this.remoteData.putData("shopping_cart", this.ShoppingCartsGoods)})Image(this.iconPath[2]).objectFit(ImageFit.Cover).height('60lpx').width('60lpx').margin({left:'40lpx',right:'50lpx'}).onClick(() => {this.iconPath[0] = this.iconPathTmp[0]this.iconPath[1] = this.iconPathTmp[1]this.iconPath[2] = this.iconPathSelectsTmp[2]this.currentPage = 3})}.margin({top:'20lpx'})}Column() {if (this.currentPage == 1) {Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End }) {Image($r("app.media.icon_share")).objectFit(ImageFit.Cover).height('60lpx').width('60lpx')}.width("100%").margin({ top: '20lpx', right: '50lpx' }).onClick(() => {this.playerDialog.open()})GoodsHome({ goodsItems: this.goodsItems})}else if (this.currentPage == 3) {//我的MyInfo()}}
3. 编写商品详细页面
3.1顶部滑动组件

1)滑动容器,提供切换子组件显示的能力;

Swiper() {ForEach(this.detailImages, item => {Image(item).height('400lpx').width('100%')})}.index(0).autoPlay(true).interval(3000).indicator(true).loop(true).height('440lpx').width('100%')
3.2 自定义弹框

1)通过 @CustomDialog 装饰器来创建自定义弹窗,使用方式可参考 自定义弹窗

2)规则弹窗效果如下,弹窗组成由两个 Text 和两个 Button 竖向排列组成;

所有我们可以在build()下使用 Flex 容器来包裹,组件代码如下:

@CustomDialog
struct CustomDialogExample {controller: CustomDialogControllercancel: () => voidconfirm: () => voidShoppingCartsGoods: any[]build() {Flex() {Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {Text('加入购物车成功').fontColor("#000000").fontSize('40lpx').margin({ top: '20lpx', bottom: "20lpx" })Flex({ justifyContent: FlexAlign.SpaceAround }) {Button('取消').onClick(() => {this.controller.close()this.cancel()}).backgroundColor(0xffffff).fontColor(Color.Black)Button('确定').onClick(() => {this.controller.close()this.confirm()}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: "20lpx" })}}.height('200lpx')}
}

3)在@entry创建CustomDialogController对象并传入弹窗所需参数,后面可通过该对象open()和close()方法进行打开和关闭弹窗;

dialogController: CustomDialogController = new CustomDialogController({builder: CustomDialogExample({cancel: this.onCancel,confirm: this.onAccept,ShoppingCartsGoods: this.ShoppingCartsGoods}),cancel: this.existApp,autoCancel: true})onCancel() {CommonLog.info('Callback when the first button is clicked')}onAccept() {CommonLog.info('Callback when the second button is clicked')router.push({uri: "pages/HomePage",params: { dataList: this.ShoppingCartsGoods }})}existApp() {CommonLog.info('Click the callback in the blank area')}
4. 添加分布式流转

分布式流转需要在同一网络下通过 DeviceManager组件 进行设备间发现和认证,获取到可信设备的deviceId调用 featureAbility.startAbility ,即可把应用程序流转到另一设备。

1)创建DeviceManager实例;

2)调用实例的startDeviceDiscovery(),开始设备发现未信任设备;

3)设置设备状态监听on(‘deviceFound’,callback),获取到未信任设备,并用discoverList变量进行维护;

4)传入未信任设备参数,调用实例authenticateDevice方法,对设备进行PIN码认证;

5)若是已信任设备,可通过实例的getTrustedDeviceListSync()方法来获取设备信息;

6)将设备信息中的deviceId传入 `featureAbility.startAbility方法,实现流转;

7)流转接收方可通过 featureAbility.getWant()获取到发送方携带的数据;

项目中将上面设备管理封装至RemoteDeviceManager,通过RemoteDeviceManager的四个方法来动态维护deviceList设备信息列表,实现分布式流转只需要在deviceList中获取deviceId,然后调用featureAbility.startAbility并携带数据,即可实现分布式流转。

5.分布式数据管理

分布式数据管理 要求两个或多个设备在同一网络,才能监听到数据库的改变,从而渲染页面;开发步骤:

1)创建一个KVManager对象实例,用于管理数据库对象;

2)通过指定Options和storeId,创建并获取KVStore数据库,如下是参数说明;需要先通过createKVManager构建一个KVManager实例;

参数名类型必填说明
storeIdstring数据库唯一标识符,长度不大于 MAX_STORE_ID_LENGTH。
optionsOptions创建KVStore实例的配置信息。

3)KVStore数据库实例, KVStore.put提供增加数据的方法,如下是参数说明;

参数名类型必填说明
keystring要添加数据的key,不能为空且长度不大于 MAX_KEY_LENGTH 。
valueUint8Arraystringnumber
callbackAsyncCallback回调函数。

4) KVStore数据库实例,KVStore.on订阅指定类型的数据变更通知;一般监听远端设备变化,再进行相应操作达到分布式数据共享的效果;

本d项目通过storeId 值不同,创建了两个数据库,分别是ShoppingCartsInfo类和TotalData类,ShoppingCartsInfo应用添加商品到购物车,TotalData应用在购物车列表进行勾选结算;如下是TotalData类流程

如下是ShoppingCartsInfo类流程

项目下载和导入

1)git下载

git clone https://gitee.com/openharmony-sig/knowledge_demo_shopping.git  --depth=1

2)项目导入

打开DevEco Studio,点击File->Open->下载路径/FA/Shopping/DistributedShoppingCart

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://gitee.com/MNxiaona/733GH

这篇关于OpenHarmony 实战开发——分布式购物车案例展示~的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Eureka高可用注册中心registered-replicas没有分布式注册中心

自己在学习过程中发现,如果Eureka挂掉了,其他的Client就跑不起来了,那既然是商业项目,还是要处理好这个问题,所以决定用《Spring Cloud微服务实战》(PDF版在全栈技术交流群中自行获取)中说的“高可用注册中心”。 一开始我yml的配置是这样的 server:port: 8761eureka:instance:hostname: 127.0.0.1client:fetch-r

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

PyTorch模型_trace实战:深入理解与应用

pytorch使用trace模型 1、使用trace生成torchscript模型2、使用trace的模型预测 1、使用trace生成torchscript模型 def save_trace(model, input, save_path):traced_script_model = torch.jit.trace(model, input)<

风水研究会官网源码系统-可展示自己的领域内容-商品售卖等

一款用于展示风水行业,周易测算行业,玄学行业的系统,并支持售卖自己的商品。 整洁大气,非常漂亮,前端内容均可通过后台修改。 大致功能: 支持前端内容通过后端自定义支持开启关闭会员功能,会员等级设置支持对接官方支付支持添加商品类支持添加虚拟下载类支持自定义其他类型字段支持生成虚拟激活卡支持采集其他站点文章支持对接收益广告支持文章评论支持积分功能支持推广功能更多功能,搭建完成自行体验吧! 原文

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

手把手教你入门vue+springboot开发(五)--docker部署

文章目录 前言一、前端打包二、后端打包三、docker运行总结 前言 前面我们重点介绍了vue+springboot前后端分离开发的过程,本篇我们结合docker容器来研究一下打包部署过程。 一、前端打包 在VSCode的命令行中输入npm run build可以打包前端代码,出现下图提示表示打包完成。 打包成功后会在前端工程目录生成dist目录,如下图所示: 把

Sapphire开发日志 (十) 关于页面

关于页面 任务介绍 关于页面用户对我组工作量的展示。 实现效果 代码解释 首先封装一个子组件用于展示用户头像和名称。 const UserGrid = ({src,name,size,link,}: {src: any;name: any;size?: any;link?: any;}) => (<Box sx={{ display: "flex", flexDirecti