鸿蒙系统采用ArkTS作为其原生开发语言。如果你对TypeScript有所了解,那么你将能够轻松过渡到ArkTS,因为它并非一种全新的语言,而是基于TypeScript的扩展。这意味着我们可以省去学习新语言的过程,只需专注于鸿蒙的UI框架——ArkUI。
慕ke慕w-鸿蒙NEXT应用开发工程师 --- “夏のke” --- Ukoou·ㄷㅁΜ
ArkUI框架与React类似,采用声明式开发模式来构建用户界面,并内置了全面的状态管理机制,无需像React那样面对众多复杂的第三方状态管理库。
鸿蒙系统的内置组件布局设计灵感来源于CSS,包括margin、padding、flex、grid、栅格系统和媒体查询等概念,这些都是Web前端开发者所熟悉的。
鸿蒙Next提供了一套完整的开发、调试、测试和发布流程,集成在一个IDE中。如果你之前使用过IntelliJ IDEA,那么你将发现使用鸿蒙的DevEco Studio是无缝的,因为它是基于IntelliJ IDEA Community版深度定制的。即使你是Neovim或VSCode的忠实用户,DevEco Studio同样易于上手。
IDE介绍
在开始之前,让我们先了解鸿蒙的IDE——DevEco Studio。
DevEco-Studio 安装
目前,DevEco Studio提供了三个版本供下载:
- Windows(64-bit)
- Mac(X86)
- Mac(ARM)
请注意,当前版本需要Node 18.x环境。对于前端开发者,建议安装nvm,并预先切换到正确的Node版本。
安装nvm后,执行以下命令:
nvm install 18.14.1
nvm use 18.14.1
node -v
这样,在安装DevEco时,你可以选择本地的Node环境。如果你的本地没有Node,也可以选择全新安装。
如果一切顺利,在Diagnose界面,你将看到所有的检查项都显示为对号,这表示安装成功。
我相信你能够自己摸索着创建一个"Hello World"项目。
接下来,你将看到项目中默认创建了大量的文件。起初,我和你一样,不知道从何下手。但经过研究,我发现许多文件都存在两个版本:一个是模块级的,另一个是应用级的。
为了更清晰地展示,我制作了一张图,图中左侧列出的文件都是应用和模块的两个版本。
整个entry目录称为一个Module,该目录将编译为一个以.hap为后缀的文件,即HAP包。
当应用最终发布时,它将被打包成一个以.app为扩展名的文件,并上传到华为应用商店。
Module不仅限于entry类型,还包括其他类型。为了简化,我仍然总结了一张图:
初看可能会感到有些困惑,但实际上,作为初学者,我们只需要关注entry模块。其他Module类型可以等到更深入的开发阶段再去文档中了解。
在entry目录下,有一个src/main/ets/pages/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%')
}
}
}
}
第一行的@Entry装饰器表明这是应用的入口点,build()方法返回的是整个声明式UI的页面结构。
翻译过来,就是在较高的Row组件中放置了一个较宽的Column组件,其中包含了一个文本组件,字体大小为50。
在右上角选择previewer,点击run按钮即可运行并预览效果。
输出效果
这就是整个开发流程。刚才的代码看起来是否非常熟悉?是的,它是TypeScript!
编程语言
鸿蒙的主要开发语言是ArkTS(以.ets文件为扩展名)。它看起来如此熟悉,因为它是TypeScript的一个超集,基本上是TS代码。最大的区别或特点是,在编译时对静态类型的检查和分析进行了增强,并对一些动态特性进行了一些限制。这使得程序在运行时类型都是已知的,减少了运行时错误并提高了程序性能。
例如,强制类型不允许使用any或unknown类型。也不能使用obj as any之类的语法动态给对象添加属性和方法,更不能在运行时使用delete删除属性或方法。在某些需要any类型的情况下,建议使用Record<string, Object>类型。
编译器默认开启了TypeScript的一些严格模式,例如strictPropertyInitialization,要求强制给定初始值。strictNullChecks强制进行空值安全检查等。
总之,你能想到的所有运行时的动态类型特性都将受到限制,尽量不要使用。更多详细的语法规则可以参考官方文档中关于《从TypeScript到ArkTS的适配规则》的文章,内容非常详细。实际上,在开发过程中,DevEco Studio会提供非常好的错误报告信息,因此你可以先不必了解这些语法规则,等到遇到问题时再去查询。
UI框架
ArkUI框架是基于ArkTS的UI框架,采用声明式开发范式,数据驱动UI更新,并提供了页面级路由导航等。
在页面布局方面,提供了多种媒体查询,例如:
- 设备类型
- 窗口宽高监听
- 折叠屏状态
- 横竖屏查询
统一了单位,例如:
vp虚拟像素fp字体像素,用户端的设置会乘以系数1fp = 1vp * scale
并提供了多种栅格系统,窗口栅格会根据容器宽度自动匹配栅格数量:
- 4格:small(360~600),手机竖屏
- 8格:medium(600~840),手机横屏,pad竖屏,折叠屏
- 12格:large(840~1440),pad横屏,2in1
- 12格:x-large(1440~),全屏
需要注意的是,目前稳定主推的应用模型称为Stage模型。如果你在学习过程中看到FA模型,那就是旧版教程,可以不用看了。
下面我们在代码层面了解一下如何声明UI。
声明式UI描述
声明式UI的描述方式如下:
Column() {
Text('item 1')
Divider()
Text('item 2')
}
Column是容器组件,所以后面带有{},包含子组件。非容器组件则无需{}。
给组件配置属性通常使用链式调用的方法:
Text(
"hello"
).fontSize(
20
).fontColor(
Color.Red
).fontWeight(
FontWeight.Bold
);
为了更加清晰,通常会写成这种格式:
Text("hello")
.fontSize(20)
.fontColor(Color.Red)
.fontWeight(FontWeight.Bold);
添加事件处理
Button("Click me").onClick(() => {
this.myText = "ArkUI";
});
装饰器
ArkUI中大量使用了装饰器,包括我们之前看到的@entry表示入口。再看一个最简单的自定义组件:
ArkUI中用@Component装饰的struct结构代表自定义组件。
@Component
struct MyComponent {
@State message: string = 'Hello, World!';
build() {
// 在build函数里返回UI描述
}
}
在当前流行的数据驱动UI编程范式中,UI = f(State),状态是不可或缺的。
ArkUI中用@State装饰器来声明状态,Parent可以直接覆盖Child State:
@Component
struct Parent {
build() {
Column() {
// 父组件覆盖State
MyComponent({ message: "hi" })
}
}
}
和React中的State类似,状态的变化可以引起UI更新,但注意这个状态不是immutable的,UI是否可以观察到状态的变化要看数据类型,具体要参考详细的文档。
下面是典型的事件处理中修改状态,引起UI刷新的例子:
@Component
export struct HelloComponent {
@State message: string = 'Hello, World!';
build() {
Row() {
Text(this.message)
.onClick(() => {
// 基础类型的状态变量message改变驱动UI刷新,
// UI从'Hello, World!'刷新为'Hello, ArkUI!'
this.message = 'Hello, ArkUI!';
})
}
}
}
@State只是组件内部的状态。如果想在状态更改时引发Child组件的更新