发表于 2024-6-24 06:37:13

HarmonyOS开发实例:【菜单app】

 简介

分布式菜单demo 模拟的是多人会餐点菜的场景,不需要扫码关注公众号等一系列操作,通过分布式数据库可以方便每个人可及时检察到订单详情,数量,总额等;效果如下


[*] demo效果

https://img-blog.csdnimg.cn/img_convert/714f6e15dfaf3770c5d943b27c4a8918.gif
工程目录

完整的项目结构目录如下
├─entry
│└─src
│      └─main
│          │config.json// 应用配置文件
│          │
│          ├─ets
│          │└─MainAbility
│          │      │app.ets// 应用程序主入口
│          │      │
│          │      ├─model
│          │      │      CommonLog.ets// 日志类
│          │      │      MenuData.ets// 初始化菜单数据类
│          │      │      MenuListDistributedData.ets// 加入菜单分布式数据库
│          │      │      RemoteDeviceManager.ets// 分布式拉起设备管理类
│          │      │      SubmitData.ets   // 结算订单分布式数据库
│          │      │      
│          │      └─pages
│          │            detailedPage.ets // 菜品详细页面
│          │            index.ets // 首页
│          │            menuAccount.ets // 订单详情页面
│          │            
│          └─resources
│            ├─base
│            │├─element
│            ││      string.json
│            ││      
│            │├─graphic
│            │├─layout
│            │├─media   // 存放媒体资源
│            ││      icon.png
│            ││      icon_add.png
│            ││      icon_back.png
│            ││      icon_cart.png
│            ││      
│            │└─profile
│            └─rawfile 鸿蒙开发文档qr23.cn/AKFP8k参考(点击或者复制前往)。
开发步调


https://img-blog.csdnimg.cn/img_convert/f8395eceeefde03fc24d54f1fc664fb7.png
1. 新建OpenHarmony ETS项目

在DevEco Studio中点击File -> New Project ->Empty Ability->Next,Language 选择ETS语言,末了点击Finish即创建乐成。 
https://img-blog.csdnimg.cn/img_convert/c81e1b9b420513cacf84382901eed368.png

https://img-blog.csdnimg.cn/img_convert/a791af403d4c26549b7626c80909aaf2.png
2. 编写商品展示主页面


https://img-blog.csdnimg.cn/img_convert/3ffd16a37bf5b7bb979c918d06695839.png
2.1用户信息

1): 主要用到容器和组件;
2): 用户名称和头像图标,根据装备序列号不同,可展示不同的名称和图标;
3): 点击右上角分享的小图标,可分布式拉起局域网内的另一台装备;
@Component
struct MemberInfo {
@Consume userImg: Resource
@Consume userName: string

aboutToAppear() {
// 根据设备序列号不同,展示不同的名称和图标
    CommonLog.info('==serial===' + deviceInfo.serial);
    if (deviceInfo.serial == '150100384754463452061bba4c3d670b') {
      this.userImg = $r("app.media.icon_user")
      this.userName = 'Sunny'
    }
    else {
      this.userImg = $r("app.media.icon_user_another")
      this.userName = 'Jenny'
    }
}

build() {
    Flex({ direction: FlexDirection.Column }) {
      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
      Image(this.userImg)
          .width('96lpx')
          .height('96lpx')
          .margin({ right: '18lpx' })
      Text(this.userName)
          .fontSize('36lpx')
          .fontWeight(FontWeight.Bold)
          .flexGrow(1)
      Image($r("app.media.icon_share"))
          .width('64lpx')
          .height('64lpx')
      }
      // 打开分布式设备列表
      .onClick(() => {
      this.DeviceDialog.open()
      })
      .layoutWeight(1)
      .padding({ left: '48lpx', right: '48lpx' })

      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
      Column() {
          Text('124')
            .fontSize('40lpx')
            .margin({ bottom: '24lpx' })
          Text('积分')
            .fontSize('22lpx')
            .opacity(0.4)
      }
      .flexGrow(1)

      Column() {
          Text('0')
            .fontSize('40lpx')
            .margin({ bottom: '24lpx' })
          Text('优惠劵')
            .fontSize('22lpx')
            .opacity(0.4)
      }
      .flexGrow(1)

      Column() {
          Image($r("app.media.icon_member"))
            .width('48lpx')
            .height('48lpx')
            .margin({ bottom: '24lpx' })
          Text('会员码')
            .fontSize('22lpx')
            .fontColor('#000000')
            .opacity(0.4)
      }
      .flexGrow(1)
      }
      .layoutWeight(1)
    }
    .width('93%')
    .height('25%')
    .borderRadius('16lpx')
    .backgroundColor('#FFFFFF')
    .margin({ top: '24lpx', bottom: '32lpx' })
}
} 2.2列表展示

1): 主要用到容器 和容器和组件;
2): 从首页点击列表进入菜品具体页面,点菜乐成后会自动返回首页,此时列表需要动态更新菜品的数量;
@Component
struct MenuHome {
private specialty: any[]
private winterNew: any[]
private classic: any[]
private soup: any[]
private menuItems: MenuData[]
private titleList = ['招牌菜', '冬季新品', '下饭菜', '汤品']
@State name: string = '招牌菜'

build() {
    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) {
      Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround }) {
      ForEach(this.titleList, item => {
          Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
            Text(item)
            .fontSize('24lpx')
          }
          .padding({ left: '24lpx' })
          .backgroundColor(this.name == item ? '#1A006A3A' : '#FFFFFF')
          .height('160lpx')
          .onClick(() => {
            this.name = item
            if (this.name == '招牌菜') {
            this.menuItems = initializeOnStartup(this.specialty);
            }
            else if (this.name == '冬季新品') {
            this.menuItems = initializeOnStartup(this.winterNew);
            }
            else if (this.name == '下饭菜') {
            this.menuItems = initializeOnStartup(this.classic);
            }
            else if (this.name == '汤品') {
            this.menuItems = initializeOnStartup(this.soup);
            }
          })
      }, item => item)
      }
      .width('20%')
      .backgroundColor('#FFFFFF')

      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): 主要用到容器 和容器和组件;
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.price * this.TotalMenu.quantity
      this.amount = this.amount + this.TotalMenu.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. 编写菜单具体页面


https://img-blog.csdnimg.cn/img_convert/87c522fc3e4c3281dd1c343b781f961e.png
3.1 菜单详情

1): 主要用到容器 和组件组件;
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 functionto 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.name == this.menuItem.name && this.TotalMenu.spicy == this.spicy) {
            this.TotalMenu.quantity = this.TotalMenu.quantity + 1;
            if (this.userName == 'Sunny') {
                this.TotalMenu.userNumber = this.TotalMenu.userNumber + 1;
            } else if (this.userName == 'Jenny') {
                this.TotalMenu.anotherUserNumber = this.TotalMenu.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. 编写订单详情页面


https://img-blog.csdnimg.cn/img_convert/bda4b0a615e29dc001cb70989abff8bb.png
4.1 订单列表

1): 主要用到容器和组件组件;
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)规则弹窗效果如下,弹窗组成由一个和两个竖向分列组成;
全部我们可以在build()下使用容器来包裹,组件代码如下:
@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.submit);
      if (data.submit == "submitOk") {
          this.SubmitDialog.open()
      }
      }
    }, "com.distributed.order", "submit")
} 5. 添加分布式流转

分布式流转需要在同一网络下通过 举行装备间发现和认证,获取到可信装备的deviceId调用 .startAbility ,即可把应用程序流转到另一装备。
1)创建DeviceManager实例;
2)调用实例的startDeviceDiscovery(),开始装备发现未信托装备;
3)设置装备状态监听on('deviceFound',callback),获取到未信托装备,并用discoverList变量举行维护;
4)传入未信托装备参数,调用实例authenticateDevice方法,对装备举行PIN码认证;
5)若是已信托装备,可通过实例的getTrustedDeviceListSync()方法来获取装备信息;
6)将装备信息中的deviceId传入.startAbility方法,实现流转;
7)流转吸取方可通过.getWant()获取到发送方携带的数据;
项目中将上面装备管理封装至RemoteDeviceManager,通过RemoteDeviceManager的四个方法来动态维护deviceList装备信息列表,实现分布式流转只需要在deviceList中获取deviceId,然后调用featureAbility.startAbility并携带数据,即可实现分布式流转。

https://img-blog.csdnimg.cn/img_convert/c10cae656346c86328c98809f4237b46.png
6.分布式数据管理

[分布式数据管理]要求两个或多个装备在同一网络,才能监听到数据库的改变,从而渲染页面;开发步调:
1)创建一个KVManager对象实例,用于管理数据库对象;
2)通过指定Options和storeId,创建并获取KVStore数据库,如下是参数说明;需要先通过createKVManager构建一个KVManager实例;
参数名范例必填说明storeIdstring是数据库唯一标识符,长度不大于。options是创建KVStore实例的配置信息。 3)KVStore数据库实例, KVStore.put提供增长数据的方法,如下是参数说明;
参数名范例必填说明keystring是要添加数据的key,不能为空且长度不大于。valueUint8Arraystringnumberboolean是要添加数据的value,支持Uint8Array、number 、 string 、boolean,Uint8Array、string 的长度不大于。callbackAsyncCallback是回调函数。 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.price * this.TotalMenu.quantity
      this.amount = this.amount + this.TotalMenu.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)资料非常有须要。 这里我推荐,根据鸿蒙开发官网梳理与华为内部职员的分享总结出的开发文档。内容包罗了:【ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。
废话就不多说了,接下来好悦目下这份资料。
如果你是一名Android、Java、前端等等开发职员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。鸿蒙OpenHarmony知识←前往。下面是鸿蒙开发的学习路线图。

https://img-blog.csdnimg.cn/img_convert/1d37453a6210a1104576ba867498219b.png

https://img-blog.csdnimg.cn/img_convert/f68b2bfb9d570beea9dc3624efe46e21.png

https://img-blog.csdnimg.cn/img_convert/6c3c59abf7036e13c8ac9fcc05d34c80.png
针对鸿蒙发展路线打造的鸿蒙学习文档。鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的门路上更进一步。
其中内容包罗:

《鸿蒙开发基础》鸿蒙OpenHarmony知识←前往

[*]ArkTS语言
[*]安装DevEco Studio
[*]运用你的第一个ArkTS应用
[*]ArkUI声明式UI开发
[*].……
《鸿蒙开发进阶》鸿蒙OpenHarmony知识←前往

[*]Stage模型入门
[*]网络管理
[*]数据管理
[*]电话服务
[*]分布式应用开发
[*]关照与窗口管理
[*]多媒体技术
[*]安全技能
[*]使命管理
[*]WebGL
[*]国际化开发
[*]应用测试
[*]DFX面向未来计划
[*]鸿蒙体系移植和裁剪定制
[*]……
《鸿蒙开发实战》鸿蒙OpenHarmony知识←前往

[*]ArkTS实践
[*]UIAbility应用
[*]网络案例
[*]……
末了

鸿蒙是完全具备无与伦比的时机和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: HarmonyOS开发实例:【菜单app】