鸿蒙HarmonyOS项目实战开辟:分布式购物车

立山  论坛元老 | 2024-6-28 18:43:50 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1865|帖子 1865|积分 5595

简介

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


  • 拉起对方用户




  • 添加商品到购物车列表




  • 购物车列表勾选




  • demo效果(HH-SCDAYU200)


工程目次

完备的项目结构目次如下
  1. ├─entry\src\main
  2. │          │  config.json  应用配置文件
  3. │          │  
  4. │          ├─ets
  5. │          │  └─MainAbility
  6. │          │      │  app.ets  ets应用程序主入口
  7. │          │      │  
  8. │          │      ├─model
  9. │          │      │      ArsData.ets     // 初始化我的页面数据
  10. │          │      │      CommonLog.ets   // 日志类
  11. │          │      │      GoodsData.ets   // 初始化商品信息数据类
  12. │          │      │      MenuData.ets    // 初始化我的页面数据类
  13. │          │      │      RemoteDeviceManager.ets  // 分布式拉起设备管理类
  14. │          │      │      ShoppingCartDistributedData.ets  // 加入购物车分布式数据库
  15. │          │      │      TotalSelectedDistributedData.ets // 结算购物车分布式数据库
  16. │          │      │      
  17. │          │      └─pages
  18. │          │              DetailPage.ets   // 商品详情页面
  19. │          │              HomePage.ets     // 应用首页
  20. │          │              MyPage.ets       // 我的页面
  21. │          │              ShoppingCartListPage.ets  // 购物车列表页面
  22. │     └─resources // 静态资源目录
  23. │         ├─base
  24. │         │  ├─element
  25. │         │  ├─graphic
  26. │         │  ├─layout
  27. │         │  ├─media // 存放媒体资源
  28. │         │  └─profile
  29. │         └─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转场动画
  1. Tabs() {
  2.         TabContent() {
  3.           GoodsList({ goodsItems: this.goodsItems});
  4.         }
  5.         .tabBar("畅销榜")
  6.         .backgroundColor(Color.White)
  7.         TabContent() {
  8.           GoodsList({ goodsItems: this.goodsItems});
  9.         }
  10.         .tabBar("推荐")
  11.         .backgroundColor(Color.White)
  12.       }
  13.        Navigator({ target: 'pages/DetailPage' }) {
  14.         Row({ space: '40lpx' }) {
  15.           Column() {
  16.             Text(this.goodsItem.title)
  17.               .fontSize('28lpx')
  18.             Text(this.goodsItem.content)
  19.               .fontSize('20lpx')
  20.             Text('¥' + this.goodsItem.price)
  21.               .fontSize('28lpx')
  22.               .fontColor(Color.Red)
  23.           }
  24.           .height('160lpx')
  25.           .width('50%')
  26.           .margin({ left: '20lpx' })
  27.           .alignItems(HorizontalAlign.Start)
  28.           Image(this.goodsItem.imgSrc)
  29.             .objectFit(ImageFit.ScaleDown)
  30.             .height('160lpx')
  31.             .width('40%')
  32.             .renderMode(ImageRenderMode.Original)
  33.             .margin({ right: '20lpx', left: '20lpx' })
  34.         }
  35.         .height('180lpx')
  36.         .alignItems(VerticalAlign.Center)
  37.         .backgroundColor(Color.White)
  38.       }
  39.       .params({ goodsItem: this.goodsItem ,ShoppingCartsGoods:this.ShoppingCartsGoods})
  40.       .margin({ left: '40lpx' })
  41.     }
  42.     // 转场动画使用系统提供的多种默认效果(平移、缩放、透明度等)
  43.   pageTransition() {
  44.     PageTransitionEnter({ duration: 1000 })
  45.       .slide(SlideEffect.Left)
  46.     PageTransitionExit({ duration: 1000  })
  47.       .slide(SlideEffect.Right)
  48.   }
复制代码
2.2底部导航栏

1)通过Row包裹三个Image组件,并添加onClick点击事件,修改@Consume修饰的变量,从而改变@Provide装饰的变量,再通过条件渲染展示不同的页面内容;
  1. Flex() {
  2.         Image(this.iconPath[0])
  3.           .objectFit(ImageFit.Cover)
  4.           .height('60lpx')
  5.           .width('60lpx')
  6.           .margin({left:'50lpx',right:'40lpx'})
  7.           .onClick(() => {
  8.             this.iconPath[0] = this.iconPathSelectsTmp[0]
  9.             this.iconPath[1] = this.iconPathTmp[1]
  10.             this.iconPath[2] = this.iconPathTmp[2]
  11.             this.currentPage = 1
  12.           })
  13.         Image(this.iconPath[1])
  14.           .objectFit(ImageFit.Cover)
  15.           .height('60lpx')
  16.           .width('60lpx')
  17.           .margin({left:'40lpx',right:'40lpx'})
  18.           .onClick(() => {
  19.             this.iconPath[0] = this.iconPathTmp[0]
  20.             this.iconPath[1] = this.iconPathSelectsTmp[1]
  21.             this.iconPath[2] = this.iconPathTmp[2]
  22.             this.currentPage = 2
  23.             this.remoteData.putData("shopping_cart", this.ShoppingCartsGoods)
  24.           })
  25.         Image(this.iconPath[2])
  26.           .objectFit(ImageFit.Cover)
  27.           .height('60lpx')
  28.           .width('60lpx')
  29.           .margin({left:'40lpx',right:'50lpx'})
  30.           .onClick(() => {
  31.             this.iconPath[0] = this.iconPathTmp[0]
  32.             this.iconPath[1] = this.iconPathTmp[1]
  33.             this.iconPath[2] = this.iconPathSelectsTmp[2]
  34.             this.currentPage = 3
  35.           })
  36.       }
  37.     .margin({top:'20lpx'})
  38.     }
  39.       
  40.       Column() {
  41.           if (this.currentPage == 1) {
  42.             Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End }) {
  43.               Image($r("app.media.icon_share"))
  44.                 .objectFit(ImageFit.Cover)
  45.                 .height('60lpx')
  46.                 .width('60lpx')
  47.             }
  48.             .width("100%")
  49.             .margin({ top: '20lpx', right: '50lpx' })
  50.             .onClick(() => {
  51.               this.playerDialog.open()
  52.             })
  53.             GoodsHome({ goodsItems: this.goodsItems})
  54.           }
  55.           else if (this.currentPage == 3) {
  56.             //我的
  57.             MyInfo()
  58.           }
  59.         }
复制代码
3. 编写商品具体页面

3.1顶部滑动组件

1)滑动容器,提供切换子组件显示的本领;
  1. Swiper() {
  2.         ForEach(this.detailImages, item => {
  3.           Image(item)
  4.             .height('400lpx')
  5.             .width('100%')
  6.         })
  7.       }
  8.       .index(0)
  9.       .autoPlay(true)
  10.       .interval(3000)
  11.       .indicator(true)
  12.       .loop(true)
  13.       .height('440lpx')
  14.       .width('100%')
复制代码
3.2 自界说弹框

1)通过**@CustomDialog**装饰器来创建自界说弹窗,利用方式可参考 自界说弹窗;
2)规则弹窗效果如下,弹窗组成由两个Text和两个Button竖向排列组成;
所有我们可以在build()下利用Flex容器来包裹,组件代码如下:
  1. @CustomDialog
  2. struct CustomDialogExample {
  3.   controller: CustomDialogController
  4.   cancel: () => void
  5.   confirm: () => void
  6.   ShoppingCartsGoods: any[]
  7.   build() {
  8.     Flex() {
  9.       Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
  10.         Text('加入购物车成功')
  11.           .fontColor("#000000")
  12.           .fontSize('40lpx')
  13.           .margin({ top: '20lpx', bottom: "20lpx" })
  14.         Flex({ justifyContent: FlexAlign.SpaceAround }) {
  15.           Button('取消')
  16.             .onClick(() => {
  17.               this.controller.close()
  18.               this.cancel()
  19.             }).backgroundColor(0xffffff).fontColor(Color.Black)
  20.           Button('确定')
  21.             .onClick(() => {
  22.               this.controller.close()
  23.               this.confirm()
  24.             }).backgroundColor(0xffffff).fontColor(Color.Red)
  25.         }.margin({ bottom: "20lpx" })
  26.       }
  27.     }
  28.     .height('200lpx')
  29.   }
  30. }
复制代码
3)在@entry创建CustomDialogController对象并传入弹窗所需参数,反面可通过该对象open()和close()方法进行打开和关闭弹窗;
  1. dialogController: CustomDialogController = new CustomDialogController({
  2.     builder: CustomDialogExample({
  3.       cancel: this.onCancel,
  4.       confirm: this.onAccept,
  5.       ShoppingCartsGoods: this.ShoppingCartsGoods
  6.     }),
  7.     cancel: this.existApp,
  8.     autoCancel: true
  9.   })
  10.   onCancel() {
  11.     CommonLog.info('Callback when the first button is clicked')
  12.   }
  13.   onAccept() {
  14.     CommonLog.info('Callback when the second button is clicked')
  15.     router.push({
  16.       uri: "pages/HomePage",
  17.       params: { dataList: this.ShoppingCartsGoods }
  18.     })
  19.   }
  20.   existApp() {
  21.     CommonLog.info('Click the callback in the blank area')
  22.   }
复制代码
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。valueUint8Array | string | number | boolean是要添加数据的value,支持Uint8Array、number 、 string 、boolean,Uint8Array、string 的长度不大于MAX_VALUE_LENGTH。callbackAsyncCallback是回调函数。 4) KVStore数据库实例,KVStore.on订阅指定类型的数据变更通知;一般监听远端设备变化,再进行相应操纵达到分布式数据共享的效果;
本d项目通过storeId 值不同,创建了两个数据库,分别是ShoppingCartsInfo类和TotalData类,ShoppingCartsInfo应用添加商品到购物车,TotalData应用在购物车列表进行勾选结算;如下是TotalData类流程


如下是ShoppingCartsInfo类流程


末了,有许多小同伴不知道学习哪些鸿蒙开辟技术?不知道需要重点把握哪些鸿蒙应用开辟知识点?而且学习时频仍踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(Harmony NEXT)资料用来跟着学习是非常有须要的。 
为了可以或许资助大家快速把握鸿蒙(Harmony NEXT)应用开辟技术知识。在此给大家分享一下我联合鸿蒙最新资料整理出来的鸿蒙南北向开辟学习蹊径以及整理的最新版鸿蒙学习文档资料。
这份鸿蒙(Harmony NEXT)资料包含了鸿蒙开辟必把握的核心知识要点,内容包含了ArkTS、ArkUI开辟组件、Stage模型、多端部署、分布式应用开辟、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开辟、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点。
希望这一份鸿蒙学习资料可以或许给大家带来资助,有需要的小同伴自行领取,限时开源,先到先得~无套路领取!!
假如你是一名有经验的资深Android移动开辟、Java开辟、前端开辟、对鸿蒙感爱好以及转行职员,可以直接领取这份资料
 获取这份完备版高清学习蹊径,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(Harmony NEXT)最新学习蹊径




  •  HarmonOS基础技能



  • HarmonOS就业必备技能 

  •  HarmonOS多媒体技术



  • 鸿蒙NaPi组件进阶



  • HarmonOS高级技能



  • 初识HarmonOS内核 

  • 实战就业级设备开辟

 有了蹊径图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布条记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开辟入门教学视频,内容包含:ArkTS、ArkUI、Web开辟、应用模型、资源分类…等知识点。
获取以上完备版高清学习蹊径,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开辟入门教学视频》


《鸿蒙生态应用开辟V2.0白皮书》


《鸿蒙 (OpenHarmony)开辟基础到实战手册》

OpenHarmony北向、南向开辟环境搭建

 《鸿蒙开辟基础》



  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开辟
  • .……

 《鸿蒙开辟进阶》



  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开辟
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开辟
  • 应用测试
  • DFX面向将来计划
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》



  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

 获取以上完备鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结

总的来说,华为鸿蒙不再兼容安卓,对中年步伐员来说是一个挑衅,也是一个机会。只有积极应对变化,不断学习和提拔自己,他们才华在这个变革的时代中立于不败之地。 



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表