最近鸿蒙比较火,所以就想着学习一下鸿蒙开发,顺便做了一个技术分享,通过了一下鸿蒙的初级开发者认证,总体来讲入门简单,基于TypeScript的,都是熟悉的TS语法和es6, 但是鸿蒙的开发模式和前端开发模式有很大的不同,需要适应。
鸿蒙初级开发者认证

基本语法、打包、组件,基本目录结构,编辑器基本使用,环境安装,arkTS、Stage模型和FA模型,组件开发的两种方式,开源鸿蒙和鸿蒙next,arkUI

背景

类前端语言,学习成本相对较低,入门上手简单。基于最新鸿蒙Next 5.0 商用版本

目标

通过本文,实现能够自己开发一个简单的应用出来,分享内容需要有一定前端基础,熟悉TypeScript、es6,css等

基本概念

华为鸿蒙系统(HUAWEI HarmonyOS)开发代号Ark(方舟),正式名称为华为终端鸿蒙智能设备操作系统软件)是由华为公司2012年以来开发的分布式操作系统,并于2019年8月正式发布。

在鸿蒙生态中,目前有3套形式不同的操作系统,分别是OpenHarmony、HarmonyOS、HarmonyOS Next。

  1. OpenHarmony 开源鸿蒙,捐赠给了开放原子基金会(是一家成立于2020年6月的非营利机构),属于完全开源的操作系统。OpenHarmony使用Linux内核,任何人都可以在gitee上下载到系统源码,并且修改和使用它。
  2. HarmonyOS由华为鸿蒙在运营,已经发布了1.0~4.0的版本,和市场上大多OS一样使用Linux内核,运行Android标准的APK应用程序。但这里注意的是,HarmonyOS并不是基于Android,而是使用了和Android相同的内核(Linux内核)。
  3. HarmonyOS NEXT则是完全去掉了AOSP(Android 开源项目)代码,实现了自主研发的鸿蒙内核,及原生的鸿蒙应用的全新操作系统。
  • 2024 一季度 harmonyOS Next开发者预览版本官网上线
  • 2024 二季度 开发者beta版本
  • 2024 四季度推出商用版本推送给用户,也就是前几天的版本,HarmonyOS 5.0.0 Release

熟悉官网

先从熟悉官网文档开始:https://developer.huawei.com/consumer/cn/develop/



目前只关注前三块内容即可。

  • 编辑器下载
  • 方舟语言文档
  • 方舟UI框架

DevEco studio编辑器的下载和安装

编辑器安装调试、报错等解决文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-deveco-studio-V5

下载

安装

安装好以后打开编辑器,选择是否导入开发工具的一些设置
导入设置

由于SDK的部分工具依赖Node.js,推荐使用配套API版本的Node.js,保证工程的兼容性。
Node.js版本

这里可以自动检测环境是否满足
自动检测

中文配置

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-software-install-V5#section4614152716

中文配置

基本使用

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-template-V5



创建好以后,先只关注入口模块的.ets(extended TypeScript)

删掉里面的内容,编写第一个页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Index.ets
@Entry
@Component
struct Index {
@State message: string = 'Hello World'

build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

  • 元素检查

页面中第一个helloworld开发成功

arkUI(方舟开发框架)

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkui-overview-V5 只介绍几个,剩下可以看文档,大概了解一下写法

组件、布局和容器组件Row和Column

  • 组件分类:容器组件和基础组件
    • 容器组件:控制排版布局,比如Row和Column
    • 基础组件:文字、图片、按钮等


控制布局的组件有很多,鸿蒙中布局方式有很多,大部分都和前端中的类似,比如:

  • 布局方式
    • 线性布局-Row&Column
    • 层叠布局-Stack
    • 弹性布局-Flex
    • 删格布局-GridRow/GridCol
    • 网格布局-Grid
    • 媒体查询
    • ….

先来看一下布局组件Row和Column组件有什么区别?字面意思,就是行和列。

  • Row组件,里面的内容呈现出水平方向排列
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Entry
    struct Index {
    build() {
    Row() {
    Text('文本1')
    Text('文本2')
    }
    }
    }
  • Column组件,里面的内容呈现出垂直方向排列
1
2
3
4
5
6
7
8
9
@Entry
struct Index {
build() {
Column() {
Text('文本1')
Text('文本2')
}
}
}

再来看一个例子

红框内的布局如何实现?总体来看按先考虑从上到下,在从左到右,也就是一个Column组件包裹三个Row组件,简单演示一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Font } from '@ohos.arkui.UIContext'

@Entry
struct Index {
@State nickName:string = 'Rick'
build() {
Column() {
Row() {
Text(this.nickName).fontWeight(FontWeight.Bold).margin({right:4})
Text('vip').width(34).height(16).linearGradient({
angle: 90,
direction: GradientDirection.Right,
colors: [["#F5DD00", 0.0], ["#F90", 1]]
}).fontColor('#fff').borderRadius(10).textAlign(TextAlign.Center)
}.width('100%')

Row() {
Text('CN')
Text('EN')
}.width('100%')

Row() {
Text('介绍内容')
}.width('100%')

Row() {
Text('tag1')
Text('tag2')
Text('tag3')
}.width('100%')
}
}
}

这样就基本实现了大概的布局
所以,布局的时候,从上到下,从左到右。先考虑上下布局,在考虑每一行的左右布局

注意点:

  • ⚠️build()下面只能有一个根元素,而且是容器组件
  • ⚠️column组件里面会默认让内容居中展示,需要给子元素设置width 100%,不然相当于一个弹性布局的div包裹了一个span,给span设置width%宽度就可以让里面的内容居中

布局按照这种树形结构

组件的属性方法

基本和前端类似,直接.xxxxx(属性)就行

文本组件

就是用来显示文本的,这里可以直接设置文本溢出展示方式,滚动等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

@Entry
struct Index {
@State nickName:string = 'Rick'
build() {
Column() {
// 超出隐藏
Text('标题').fontSize(30)
Text('具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述')
.textOverflow({
overflow:TextOverflow.Ellipsis
}).maxLines(2) //设置最大展示行数


// 滚动
Text('标题').fontSize(30)
Text('具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述具体内容描述').width('100%')
.textOverflow({
overflow:TextOverflow.MARQUEE
}).maxLines(3) //设置最大展示行数
}
}
}

image组件、资源加载以及引用

  • 支持网络地址和本地地址
    • 真机或者模拟器,网络地址需要在module.json5 配置ohos.permission.PERMISSION 网络权限才行

图片一般放在resources/base/media目录下,引用media下面的资源需要使用$r(‘app.media.图片’),不带后缀

svg资源导入和修改颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


@Entry
struct Index {
@State nickName:string = 'Rick'
build() {
Column() {
// 网络地址
// Image('https://ali-global-cdn.hellotalk8.com/default.jpg?x-oss-process=style/small&')

// 本地路径
Image($r('app.media.background')).width(100)

//svg资源
Image($r('app.media.VIP')).width(100)
//svg填充颜色
Image($r('app.media.VIP')).width(100).fillColor('red')


}
}
}

官方图标库:https://developer.huawei.com/consumer/cn/design/harmonyos-icon/

动画

动画部分相对于写css简单很多,同样也提供了大量动画类型:

  • 属性动画
  • 转场动画
  • 粒子动画
  • 组件动画
  • 动画曲线
  • 动画衔接
  • 动画效果
  • 帧动画

属性动画

常见的比如显示隐藏,位移,大小变化等

  • animationTo:需要嵌套使用动画,多个动画属性参数相同的情况
  • animation:多个动画属性参数不相同的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { curves } from '@kit.ArkUI';

@Entry
struct Index {
@State cubeSize:number = 100
@State cubeSize2:number = 100
@State cubeColor:Color = Color.Green
build() {
Column({space:10}) {
// animationTo
Row() {
Text('cubeSize')
}
.width(this.cubeSize)
.height(this.cubeSize)
.backgroundColor(Color.Red)
.onClick(() => {
this.getUIContext()?.animateTo({ curve: curves.springMotion() }, () => {
this.cubeSize = 200 // 添加点击事件,变化属性,animateTo需要把动画属性放入到闭包中
})
})

// animation,属性变化自动执行动画
Row({space:10}) {
Text('cubeSize2')
}
.width(this.cubeSize2)
.height(this.cubeSize2)
.backgroundColor(this.cubeColor)
.animation({ curve: curves.springMotion() })
.onClick(() => {
this.cubeSize2 = this.cubeSize2 === 200 ? 100:200
this.cubeColor = this.cubeSize2 === 200 ? Color.Red : Color.Green
})


}
}
}

单位以及转换

鸿蒙系统中,存在以下几种单位:

不设置单位,默认就是vp,fp和lpx不用管,适应不同的物理像素单位。
单位之间可以互相转换,比如vp2px(100),可以转换为px,之前有一个背景图问题现在修复了就不涉及了。

背景图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@Entry
struct Index {
build() {
Column({space:10}) {
Row() {
}
.width(this.cubeSize)
.height(this.cubeSize)
.backgroundColor(Color.Pink)
.backgroundImage($r('app.media.background'))
.backgroundImagePosition({
x:150,
y:150
})
}
}
}

弹性布局

和css大同小异,代码简单演示一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

@Entry
struct Index {
build() {
Flex({
//设置对齐方向,主轴,交叉轴,倒着等
direction: FlexDirection.Column,
// 主轴对齐方式
justifyContent: FlexAlign.Center,
// 交叉轴对齐
alignItems: ItemAlign.Center
// 可以拉伸
// alignItems: ItemAlign.Stretch
}) {
Text()
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.border({
width: 1,
color:Color.Black
})

Text()
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.border({
width: 1,
color:Color.Black
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Pink)
.border({
width: 1,
color:Color.Black
})
}
.height(500)
.width('100%')
.backgroundColor(Color.Green)
}
}

绝对定位和z-index层级

和css一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

@Entry
struct Index {
build() {
Column() {
Text('文本')
.width(50)
.height(50)
.backgroundColor(Color.Pink)
.position({ //通过position绝对定位元素
x: 100,
y: 50
}).zIndex(5) //增加zIndex会覆盖到下面

Text('文本2')
.width(50)
.height(50)
.backgroundColor(Color.Red)
.position({
x: 100,
y: 80
})
}
}
}

声明式开发范式和类web开发(仅作了解)

仅作了解,官方推荐Stage模型的ArkTS和ArkUI实现,这个是FA 模型
兼容通过HML、CSS、JavaScript三段式开发方式,来开发组件。快速将已有的Web应用改造成方舟开发框架应用。主要适用于界面较为简单的中小型应用开发。

提供了一套完整的UI框架,可以直接在项目中去使用。叫做方舟开发框架(ArkUI框架),可以用两种方式开发:arkTS和 javaScript

arkTS

ArkTS 在继承了Typescript语法的基础上,主要扩展了声明式UI开发相关的能力。
语法就不讲了,完全就是es6,TypeScript,有些写法不一样的,看一眼就明白了

组件

  • 一个.ets文件只能有一个@Entry
  • 直接输入comp可以快速生成基本结构
  • 支持拥有自己的State

可以在目录下创建一个components目录,和Vue一样,然后再import进来

  1. 创建目录
  2. 创建组件
  3. import到有@Entry的文件中
1
2
3
4
5
6
7
8
// 子组件 MyComp.ets
@Component
export struct MyComp{
build() {
Text('子组件')
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// page/Index.ets
import { MyComp } from '../components/MyComp'

@Entry
struct Index {
build() {
Column() {
MyComp()
MyComp()


// 组件可以设置自己的样式,点击事件
MyComp().backgroundColor(Color.Red).onClick(() => {
AlertDialog.show({
message: '11111'
})
})
}
}
}

组件传递值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Preview
@Component
export struct MyComp{
// 定义接收的props
@State text:string = ''
getMore = () => {

}
build() {
Text(this.text).onClick(() => {
this.getMore()
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { MyComp } from '../components/MyComp'


@Entry
struct Index {
build() {
Column() {
MyComp({
// 可以传入props传递值
text: '父组件传入的Props',
// 方法也可以传入
getMore() {
AlertDialog.show({
message: '1111'
})
}
}).backgroundColor(Color.Red).onClick(() => {
AlertDialog.show({
message: '11111'
})
})
}
}
}

@Preview

组件增加@Preview修饰符,可以预览

切换到组件预览模式,重新开启关闭预览器可以看到只预览组件

1
2
3
4
5
6
7
8
@Preview
@Component
export struct MyComp{
@State text:string = ''
build() {
Text(this.text)
}
}

@buildParams

有点类似插槽

ArkUI-X

将鸿蒙应用编译到其他平台、类似RN,Flutter

官方demo最佳实践

https://gitee.com/harmonyos_samples/hmosworld
鸿蒙世界App

其他