Flex({ direction: FlexDirection.Column }) {
Text(this.name)
.fontSize('32lpx')
.fontWeight(FontWeight.Bold)
.opacity(0.4)
.height('8%')
Scroll() {
Column() {
List() {
ForEach(this.menuItems, item => {
ListItem() {
MenuListItem({ menuItem: item })
}
}, item => item.id.toString())
}
}
}
.height('92%')
}
.margin({ left: '10lpx' })
.width('75%')
}
.height('50%')
}
}
###### 2.3底部总额
1): 主要用到[Flex]( )容器 和[Stack]( )容器[Image]( )和[Text]( )组件;
2): 从首页点击列表进入菜品详细页面,点菜成功后会自动返回首页,更新订单数量和总额;
3): 点击底部总额框,将订单列表加入分布式数据库,@entry模拟监听数据库变化,拉起订单列表详情页面;
@Component
struct TotalInfo {
@Consume TotalMenu: any[];
private total: number = 0;
private amount: number = 0;
private remoteData: MenuListData
aboutToAppear() {
for (var index = 0; index < this.TotalMenu.length; index++) {
this.total = this.total + this.TotalMenu[index].price * this.TotalMenu[index].quantity
this.amount = this.amount + this.TotalMenu[index].quantity
}
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Stack({ alignContent: Alignment.Center }) {
Image($r(“app.media.icon_cart”))
.width(‘96lpx’)
.height(‘96lpx’)
.margin({ left: ‘22lpx’ })
Text(this.amount.toString())
.backgroundColor(‘#F84747’)
.borderRadius(‘30plx’)
.fontSize(‘24plx’)
.textAlign(TextAlign.Center)
.fontColor(‘#FFFFFF’)
.width(‘50lpx’)
.height(‘50lpx’)
.margin({ left: ‘100lpx’, bottom: ‘85lpx’ })
}
.width(‘150lpx’)
.height(‘150lpx’)
Text('¥')
.fontSize('22lpx')
.fontColor('#006A3A')
.margin({ left: '22lpx' })
Text(this.total.toString())
.fontSize('40lpx')
.fontColor('#006A3A')
.flexGrow(1)
Text('点好了')
.height('100%')
.width('35%')
.fontColor('#FFFFFF')
.backgroundColor('#F84747')
.textAlign(TextAlign.Center)
}
// 将总的订单数据,加入分布式数据库
.onClick(() => {
this.remoteData.putData("menu_list", this.TotalMenu)
})
.width('100%')
.height('10%')
.backgroundColor('#FFFFFF')
}
}
##### 3. 编写菜单详细页面
![image-20211124093106260](https://img-blog.csdnimg.cn/img_convert/5223d79e1d152c8edc310c0089208cbb.png)
###### 3.1 菜单详情
1): 主要用到[Flex]( )容器 [Image]( )和[Text]( )组件[Button]( )组件;
2): 辣度可以选择;
3):点击选好了,需要判断该菜品是否已经在总订单里面,并判断是哪一个用户添加,根据判断,做出相应的增加;
@Component
struct detailInfo {
private menuItem
private spicyList = [‘正常辣’, ‘加辣’, ‘少辣’]
@State spicy: string = ‘正常辣’
private TotalMenu: any[]
private index = 0
private userName: string
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {
Flex({ direction: FlexDirection.Row }) {
Flex() {
Image(this.menuItem.imgSrc)
.objectFit(ImageFit.Contain)
}
Flex({ direction: FlexDirection.Column }) {
Text(this.menuItem.name)
.fontSize('32lpx')
.flexGrow(1)
Text(this.menuItem.remarks)
.fontSize('22lpx')
.fontColor('#000000')
.opacity(0.6)
.flexGrow(1)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Text('¥')
.fontSize('22lpx')
Text(this.menuItem.price.toString())
.fontSize('40lpx')
Text('/份')
.fontSize('22lpx')
.flexGrow(1)
Image($r("app.media.icon_reduce"))
.width('44lpx')
.height('44lpx')
.onClick(() => {
prompt.showToast({
message: "Reduce function to be completed",
duration: 5000
})
})
Text(this.menuItem.quantity.toString())
.margin({ left: '15lpx', right: '15lpx' })
Image($r("app.media.icon_add"))
.width('44lpx')
.height('44lpx')
.margin({ right: '15lpx' })
.onClick(() => {
prompt.showToast({
message: "Increase function to be completed",
duration: 5000
})
})
}
.flexGrow(2)
}
}
.height('40%')
.margin({ top: '40lpx', bottom: '24lpx' })
Button()
.backgroundColor('#000000')
.opacity(0.1)
.height('2lpx')
.margin({ left: '24lpx' })
.width('92%')
Flex({ direction: FlexDirection.Row }) {
Button()
.backgroundColor('#006A3A ')
.width('8lpx')
.height('48lpx')
.margin({ right: '12lpx' })
Text('辣度')
}
.margin({ left: '44lpx', top: '48lpx', bottom: '32lpx' })
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceEvenly }) {
ForEach(this.spicyList, item => {
Button(item)
.fontSize('28lpx')
.height('60lpx')
.width('156lpx')
.borderRadius('12lpx')
.backgroundColor(this.spicy == item ? '#006A3A' : '#0D000000')
.fontColor(this.spicy == item ? '#FFFFFF' : '#000000')
.onClick(() => {
this.spicy = item
})
}, item => item)
}
}
.margin({ top: '56lpx' })
.width('92%')
.height('50%')
.borderRadius('16lpx')
.backgroundColor('#FFFFFF')
Button('选好了')
.fontSize('36lpx')
.width('80%')
.height('7%')
.backgroundColor('#F84747')
.onClick(() => {
for (this.index = 0; this.index < this.TotalMenu.length; this.index++) {
if (this.TotalMenu[this.index].name == this.menuItem.name && this.TotalMenu[this.index].spicy == this.spicy) {
this.TotalMenu[this.index].quantity = this.TotalMenu[this.index].quantity + 1;
if (this.userName == 'Sunny') {
this.TotalMenu[this.index].userNumber = this.TotalMenu[this.index].userNumber + 1;
} else if (this.userName == 'Jenny') {
this.TotalMenu[this.index].anotherUserNumber = this.TotalMenu[this.index].anotherUserNumber + 1;
}
break;
}
}
// 菜名不一样,辣度不一样,都需要重新push到列表里面
if (this.index == this.TotalMenu.length) {
this.menuItem.spicy = this.spicy;
this.menuItem.quantity = 1;
//根据不用的用户名称,
if (this.userName == 'Sunny') {
this.menuItem.userNumber = 1;
} else if (this.userName == 'Jenny') {
this.menuItem.anotherUserNumber = 1;
}
this.TotalMenu.push(this.menuItem);
}
router.push({
uri: 'pages/index',
params: { menuItem: this.menuItem, TotalMenu: this.TotalMenu }
})
})
.margin({ top: '10%' })
}
}
}
##### 4. 编写订单详情页面
![image-20211124093106260](https://img-blog.csdnimg.cn/img_convert/0f46bfc948bcab2eab5152ab339a403d.png)
###### 4.1 订单列表
1): 主要用到[Flex]( )容器[Image]( )和[Text]( )组件[Button]( )组件;
2): 点击下单,将"submitOk" 加入分布式数据库,监听数据库变化后,弹出自定义对话框;
@Component
struct TotalItem {
private totalMenu: MenuData
build() {
Flex({ direction: FlexDirection.Column }) {
Flex({ direction: FlexDirection.Row, alignContent: FlexAlign.Start, justifyContent: FlexAlign.Start }) {
Image(this.totalMenu.imgSrc)
.width('210lpx')
.height('100%')
Flex({ direction: FlexDirection.Column }) {
Text(this.totalMenu.name)
.fontSize('32lpx')
.flexGrow(1)
Text(this.totalMenu.spicy)
.fontSize('22lpx')
.fontColor('#000000')
.opacity(0.6)
.flexGrow(1)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Text('¥')
.fontSize('22lpx')
Text(this.totalMenu.price.toString())
.fontSize('40lpx')
Text('/份')
.fontSize('22lpx')
.flexGrow(1)
Text(this.totalMenu.quantity.toString())
.fontColor("#F84747")
.fontSize('40lpx')
}
.flexGrow(2)
}
.padding({ left: '5%', top: '6%' })
.width('70%')
}
.height('180lpx')
Button()
.backgroundColor('#000000')
.opacity(0.1)
.height('2lpx')
.margin({ top: '20lpx' })
.width('100%')
if (this.totalMenu.userNumber > 0) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Image(this.totalMenu.userImg)
.width('96lpx')
.height('96lpx')
Text(this.totalMenu.userName)
.fontSize('36lpx')
.fontWeight(FontWeight.Bold)
.margin({ left: '12lpx' })
.flexGrow(1)
Text(this.totalMenu.userNumber.toString())
.fontSize('32lpx')
.margin({ right: '11plx' })
}
.height('150lpx')
}
if (this.totalMenu.anotherUserNumber > 0) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Image(this.totalMenu.anotherUserImg)
.width('96lpx')
.height('96lpx')
Text(this.totalMenu.anotherUserName)
.fontSize('36lpx')
.fontWeight(FontWeight.Bold)
.margin({ left: '12lpx' })
.flexGrow(1)
Text(this.totalMenu.anotherUserNumber.toString())
.fontSize('32lpx')
.margin({ right: '11plx' })
}
.height('150lpx')
}
}
.margin({ top: '12lpx' })
.borderRadius('16lpx')
.padding({ left: '3%', right: '3%', top: '2%' })
.backgroundColor('#FFFFFF')
}
}
###### 4.2自定义弹框
1)通过\*\*@CustomDialog\*\*装饰器来创建自定义弹窗,使用方式可参考 [自定义弹窗]( );
2)规则弹窗效果如下,弹窗组成由一个[Image]( )和两个[Text]( )竖向排列组成;
所有我们可以在build()下使用[Flex]( )容器来包裹,组件代码如下:
@CustomDialog
struct SubmitDialog {
private controller: CustomDialogController
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Flex({ justifyContent: FlexAlign.Center }) {
Image($r(“app.media.icon_success”))
.width(‘100lpx’)
.height(‘80lpx’)
}
.flexGrow(1)
Text('下单成功')
.fontSize('36lpx')
.fontColor('#000000')
.flexGrow(1)
Text('*温馨提示:菜品具体售卖情况请以店面实际情况为准哦~')
.fontSize('22lpx')
.opacity(0.6)
.fontColor('#000000')
.padding({ left: '10lpx', right: '10lpx' })
}
.height('300lpx')
.width('100%')
.padding({ top: '50lpx', bottom: '20lpx' })
}
}
3)在@entry创建CustomDialogController对象并传入弹窗所需参数,设置点击允许点击遮障层退出,通过open()方法,显示弹窗;
SubmitDialog: CustomDialogController = new CustomDialogController({
builder: SubmitDialog(),
autoCancel: true
})
aboutToAppear() {
this.remoteData.createManager(() => {
let self = this;
var data;
if (JSON.stringify(self.remoteData.dataItem).length > 0) {
data = self.remoteData.dataItem;
CommonLog.info("======submit==" + data[0].submit);
if (data[0].submit == "submitOk") {
this.SubmitDialog.open()
}
}
}, "com.distributed.order", "submit")
}
##### 5. 添加分布式流转
分布式流转需要在同一网络下通过 [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并携带数据,即可实现分布式流转。**
![RemoteDeviceManager](https://img-blog.csdnimg.cn/img_convert/c908bdbf9ae6b6805d2b25614593d4f3.png)
##### 6.分布式数据管理
[分布式数据管理]( )要求两个或多个设备在同一网络,才能监听到数据库的改变,从而渲染页面;开发步骤:
1)创建一个KVManager对象实例,用于管理数据库对象;
2)通过指定Options和storeId,创建并获取KVStore数据库,如下是参数说明;需要先通过createKVManager构建一个KVManager实例;
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| storeId | string | 是 | 数据库唯一标识符,长度不大于[MAX\_STORE\_ID\_LENGTH]( )。 |
| options | [Options]( ) | 是 | 创建KVStore实例的配置信息。 |
3)KVStore数据库实例, KVStore.put提供增加数据的方法,如下是参数说明;
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| key | string | 是 | 要添加数据的key,不能为空且长度不大于[MAX\_KEY\_LENGTH]( )。 |
| value | Uint8Array | string | number | boolean | 是 | 要添加数据的value,支持Uint8Array、number 、 string 、boolean,Uint8Array、string 的长度不大于[MAX\_VALUE\_LENGTH]( )。 |
| callback | AsyncCallback | 是 | 回调函数。 |
4) KVStore数据库实例,KVStore.on订阅指定类型的数据变更通知;一般监听远端设备变化,再进行相应操作达到分布式数据共享的效果;
**本项目通过storeId 值不同,创建了两个数据库,分别是MenuListDistributedData类和SubmitData类;**
**MenuListDistributedData是将完整订单添加到分布式数据库**
@Component
struct TotalInfo {
@Consume TotalMenu: any[];
private total: number = 0;
private amount: number = 0;
private remoteData: MenuListData
aboutToAppear() {
for (var index = 0; index < this.TotalMenu.length; index++) {
this.total = this.total + this.TotalMenu[index].price * this.TotalMenu[index].quantity
this.amount = this.amount + this.TotalMenu[index].quantity
}
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Stack({ alignContent: Alignment.Center }) {
Image($r(“app.media.icon_cart”))
.width(‘96lpx’)
.height(‘96lpx’)
.margin({ left: ‘22lpx’ })
Text(this.amount.toString())
.backgroundColor(‘#F84747’)
.borderRadius(‘30plx’)
.fontSize(‘24plx’)
.textAlign(TextAlign.Center)
.fontColor(‘#FFFFFF’)
.width(‘50lpx’)
.height(‘50lpx’)
.margin({ left: ‘100lpx’, bottom: ‘85lpx’ })
}
.width(‘150lpx’)
.height(‘150lpx’)
Text('¥')
.fontSize('22lpx')
.fontColor('#006A3A')
.margin({ left: '22lpx' })
Text(this.total.toString())
.fontSize('40lpx')
.fontColor('#006A3A')
.flexGrow(1)
Text('点好了')
.height('100%')
.width('35%')
.fontColor('#FFFFFF')
.backgroundColor('#F84747')
.textAlign(TextAlign.Center)
}
.onClick(() => {
this.remoteData.putData("menu_list", this.TotalMenu)
})
.width('100%')
.height('10%')
.backgroundColor('#FFFFFF')
}
}
**SubmitData在订单结算是点击下单,将submitOk 添加到数据库;**
@Component
struct SubmitList {
private remoteData: SubmitData
private SubmitOK: any[] = [
{
submit: “submitOk”
}
];
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text(‘下单’)
.fontSize(‘36lpx’)
.fontColor(‘#FFFFFF’)
}
.width(‘100%’)
.height(‘10%’)
.backgroundColor(‘#F84747’)
.onClick(() => {
this.remoteData.putData(“submit”, this.SubmitOK)
})
.margin({ top: ‘5%’ })
}
}
最后,有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的**鸿蒙(Harmony NEXT)资料**用来跟着学习是非常有必要的。
为了能够帮助大家快速掌握**鸿蒙(Harmony NEXT)**应用开发技术知识。**在此给大家分享一下我结合鸿蒙最新资料整理出来的鸿蒙南北向开发学习路线以及整理的最新版鸿蒙学习文档资料。**
**这份鸿蒙(Harmony NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了**(**ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony****多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)**技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,**限时开源,先到先得~无套路领取!!**
**如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料**
**获取这份完整版高清学习路线,请点击→**[纯血版全套鸿蒙HarmonyOS学习资料]( )****
### **鸿蒙(Harmony NEXT)最新学习路线**
**![](https://img-blog.csdnimg.cn/direct/309a2ac95b5d40aa8c0f79885edb295a.png)**
* **HarmonOS基础技能**
![](https://img-blog.csdnimg.cn/direct/72fd2509a44e4bf98bbe1f983b5a4ff6.png)
* **HarmonOS就业必备技能** ![](https://img-blog.csdnimg.cn/direct/18f024bc5f0a4353912996010ed6cc81.png)
* **HarmonOS多媒体技术**
![](https://img-blog.csdnimg.cn/direct/b9ead66dadc245fdadce4d77feb47a28.png)
* **鸿蒙NaPi组件进阶**
![](https://img-blog.csdnimg.cn/direct/0744fbd1454f41b0a3f605fb4a51f5f3.png)
* **HarmonOS高级技能**
![](https://img-blog.csdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
* **初识HarmonOS内核**![](https://img-blog.csdnimg.cn/direct/9e79fbdc4bb74f179584c5552aa547d5.png)
* **实战就业级设备开发**
![](https://img-blog.csdnimg.cn/direct/d2012fa9c57a400da25a2182a38cbdcb.png)
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的**鸿蒙(OpenHarmony )学习手册(共计1236页)**与**鸿蒙(OpenHarmony )开发入门教学视频**,内容包含:**ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。**
**获取以上完整版高清学习路线,请点击→[纯血版全套鸿蒙HarmonyOS学习资料]( )**
#### **《鸿蒙 (OpenHarmony)开发入门教学视频》**
![](https://img-blog.csdnimg.cn/direct/ad3cb3acb77e470fa93ac0471d4e7f0f.png)
#### 《鸿蒙生态应用开发V2.0白皮书》
![图片](https://img-blog.csdnimg.cn/img_convert/bf439a395d3ce8e8cf3dee8e8b75e3a9.jpeg)
#### **《鸿蒙 (OpenHarmony)开发基础到实战手册》**
OpenHarmony北向、南向开发环境搭建
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/1ab4c9b5659bd859d440f73d560de6b0.png)
![img](https://img-blog.csdnimg.cn/img_convert/58d23d7c7652027d5a8461cf3fe17152.png)
![img](https://img-blog.csdnimg.cn/img_convert/fe7e7832f976f7909341a8368171d576.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)**
![img](https://img-blog.csdnimg.cn/img_convert/8f484403ca94209196b7e90721ccce92.png)
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中...(img-RszSJgga-1712922315620)]
[外链图片转存中...(img-HC3eB4le-1712922315621)]
[外链图片转存中...(img-WYK6lgZl-1712922315621)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)**
[外链图片转存中...(img-TiknWWLA-1712922315621)]
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**