马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
简介
分布式菜单demo 模拟的是多人会餐点菜的场景,不需要扫码关注公众号等一系列操作,通过分布式数据库可以方便每个人可及时检察到订单详情,数量,总额等;效果如下
工程目录
完整的项目结构目录如下
- ├─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参考(点击或者复制前往)。
开发步调
1. 新建OpenHarmony ETS项目
在DevEco Studio中点击File -> New Project ->Empty Ability->Next,Language 选择ETS语言,末了点击Finish即创建乐成。
2. 编写商品展示主页面
2.1用户信息
1): 主要用到[Flex]容器[Image]和[Text]组件;
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): 主要用到[Flex]容器 和[Scroll]容器[Image]和[Text]组件;
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): 主要用到[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. 编写菜单具体页面
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. 编写订单详情页面
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并携带数据,即可实现分布式流转。
6.分布式数据管理
[分布式数据管理]要求两个或多个装备在同一网络,才能监听到数据库的改变,从而渲染页面;开发步调:
1)创建一个KVManager对象实例,用于管理数据库对象;
2)通过指定Options和storeId,创建并获取KVStore数据库,如下是参数说明;需要先通过createKVManager构建一个KVManager实例;
参数名范例必填说明storeIdstring是数据库唯一标识符,长度不大于[MAX_STORE_ID_LENGTH]。options[Options]是创建KVStore实例的配置信息。 3)KVStore数据库实例, KVStore.put提供增长数据的方法,如下是参数说明;
参数名范例必填说明keystring是要添加数据的key,不能为空且长度不大于[MAX_KEY_LENGTH]。valueUint8Arraystringnumberboolean是要添加数据的value,支持Uint8Array、number 、 string 、boolean,Uint8Array、string 的长度不大于[MAX_VALUE_LENGTH]。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[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)资料非常有须要。 这里我推荐,根据鸿蒙开发官网梳理与华为内部职员的分享总结出的开发文档。内容包罗了:【ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。
废话就不多说了,接下来好悦目下这份资料。
如果你是一名Android、Java、前端等等开发职员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。鸿蒙OpenHarmony知识←前往。下面是鸿蒙开发的学习路线图。
针对鸿蒙发展路线打造的鸿蒙学习文档。鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的门路上更进一步。
其中内容包罗:
《鸿蒙开发基础》鸿蒙OpenHarmony知识←前往
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》鸿蒙OpenHarmony知识←前往
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 关照与窗口管理
- 多媒体技术
- 安全技能
- 使命管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来计划
- 鸿蒙体系移植和裁剪定制
- ……
《鸿蒙开发实战》鸿蒙OpenHarmony知识←前往
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
末了
鸿蒙是完全具备无与伦比的时机和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |