ArkTS模型
TypeScript语法
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS,Microsoft)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。
基础
let 、const、var
作用域: var
是函数作用域,这意味着如果你在函数内部使用 var
声明一个变量,那么这个变量在整个函数内部都可以访问。而 let
是块级作用域,只能在声明它的块或子块中访问。
使用 let 可以减少由于编程错误或误解引起的bug数量,并且强制执行更强大、更易理解、更可预测的编程模式。
TypeScript 提供了 string
关键字来表示字符串类型,使用单引号('
)或双引号("
)来表示字符串类型,也可以使用反引号(**`**)来定义多行文本和内嵌表达式。
1 |
|
可选参数
1 |
|
箭头函数
ES6版本的TypeScript提供了一个箭头函数,它是定义匿名函数的简写语法,用于函数表达式,它省略了function关键字。箭头函数的定义如下,其函数是一个语句块:
1 |
|
其中,括号内是函数的入参,可以有0到多个参数,箭头后是函数的代码块。我们可以将这个箭头函数赋值给一个变量,如下所示:
1 |
|
类:和Java类似,有new、extends、this、public、private、protected
1 |
|
for..of和for..in均可迭代一个列表,但是用于迭代的值却不同:for..in迭代的是对象的键,而for..of则迭代的是对象的值。
1 |
|
module
随着应用越来越大,通常要将代码拆分成多个文件,即所谓的模块(module)
两个模块之间的关系是通过在文件级别上使用 import 和 export 建立的。模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。
1 |
|
ArkTS
基本UI描述
- 装饰器:用来装饰类、结构体、方法以及变量,赋予其特殊的含义,如上述示例中 @Entry 、 @Component 、 @State 都是装饰器。具体而言, @Component 表示这是个自定义组件; @Entry 则表示这是个入口组件; @State 表示组件中的状态变量,这个状态变化会引起 UI 变更。
- 自定义组件:可复用的 UI 单元,可组合其它组件,如上述被 @Component 装饰的 struct Hello。
ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结构,构成一个自定义组件。自定义组件中提供了一个build函数,开发者需在该函数内以链式调用的方式进行基本的UI描述,UI描述的方法请参考UI描述规范。
基本概念
- *struct:自定义组件可以基于struct实现,不能有继承关系,对于struct的实例化,可以省略new。
- *装饰器:装饰器给被装饰的对象赋予某一种能力,其不仅可以装饰类或结构体,还可以装饰类的属性。多个装饰器可以叠加到目标元素上,定义在同一行中或者分开多行,推荐分开多行定义。
1
2
3
4@Entry
@Component
struct MyComponent {
}
- @Component:装饰struct,结构体在装饰后具有基于组件的能力,需要实现build方法来创建UI。
- @Entry: 装饰struct,组件被装饰后作为页面的入口,页面加载时将被渲染显示
- @Preview:装饰struct, 用@Preview装饰的自定义组件可以在DevEco Studio的预览器上进行实时预览,加载页面时,将创建并显示@Preview装饰的自定义组件。
状态管理
基本概念-状态管理-ArkTS语法(声明式UI)-学习ArkTS语言-开发基础知识-入门-HarmonyOS应用开发
ArkTS提供了多维度的状态管理机制,在UI开发框架中,和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,也可以是全局范围内的传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递
页面级变量的状态管理
页面级变量的状态管理-状态管理-ArkTS语法(声明式UI)-学习ArkTS语言-开发基础知识-入门-HarmonyOS应用开发
@State
@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
- 支持多种类型数据:支持class、number、boolean、string强类型数据的值类型和引用类型,不支持object和any。
- 内部私有:标记为@State的属性是私有变量,只能在组件内访问
- 需要本地初始化:必须为所有@State变量分配初始值
@Prop
@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但变量的更改不会通知给父组件,父组件变量的更改会同步到@prop装饰的变量,即@Prop属于单向数据绑定。
@Prop状态数据具有以下特征:
- 支持简单类型:仅支持number、string、boolean等简单数据类型;
- 私有:仅支持组件内访问;
- 支持多个实例:一个组件中可以定义多个标有@Prop的属性;
- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。
==实现子组件从父子组件单向状态同步 : @State和@Prop==
@Link
@Link装饰的变量可以和父组件的@State变量建立双向数据绑定,@Link变量不能在组件内部进行初始化。
我们对于视图更新,可以使用@State
标记变量,但是@State
不能进行跨文件使用。这个时候@Link
的实现就弥补了@State
的不足。使用@Link
的话。子组件中被@Link
装饰的变量与其父组件中对应的数据源建立双向数据绑定。
==子组件@Link装饰的变量可以和父组件的@State变量建立双向数据绑定。==
@Observed和ObjectLink数据管理
当开发者只想针对父组件中某个数据对象的部分信息进行同步时,使用@Link就不能满足要求。如果这些部分信息是一个类对象,就可以使用@ObjectLink配合@Observed来实现,如下图所示。
- @Observed用于类,@ObjectLink用于变量。
- @ObjectLink装饰的变量类型必须为类(class type)。
- 类要被@Observed装饰器所装饰。
- 不支持简单类型参数,可以使用@Prop进行单向同步。
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63// xxx.ets
// 父组件ViewB中的类对象ClassA与子组件ViewA保持数据同步时,可以使用@ObjectLink和@Observed,绑定该数据对象的父组件和其他子组件同步更新
var nextID: number = 0
@Observed
class ClassA {
public name: string
public c: number
public id: number
constructor(c: number, name: string = 'OK') {
this.name = name
this.c = c
this.id = nextID++
}
}
@Component
struct ViewA {
label: string = 'ViewA1'
@ObjectLink a: ClassA
build() {
Row() {
Button(`ViewA [${this.label}] this.a.c= ${this.a.c} +1`)
.onClick(() => {
this.a.c += 1
})
}.margin({ top: 10 })
}
}
@Entry
@Component
struct ViewB {
@State arrA: ClassA[] = [new ClassA(0), new ClassA(0)]
build() {
Column() {
ForEach(this.arrA, (item) => {
ViewA({ label: `#${item.id}`, a: item })
}, (item) => item.id.toString())
ViewA({ label: `this.arrA[first]`, a: this.arrA[0] })
ViewA({ label: `this.arrA[last]`, a: this.arrA[this.arrA.length - 1] })
Button(`ViewB: reset array`)
.margin({ top: 10 })
.onClick(() => {
this.arrA = [new ClassA(0), new ClassA(0)]
})
Button(`ViewB: push`)
.margin({ top: 10 })
.onClick(() => {
this.arrA.push(new ClassA(0))
})
Button(`ViewB: shift`)
.margin({ top: 10 })
.onClick(() => {
this.arrA.shift()
})
}.width('100%')
}
}
@Consume和@Provide
@Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。@Consume在感知到@Provide数据的更新后,会触发当前自定义组件的重新渲染。
应用级变量的状态管理
应用级变量的状态管理-状态管理-ArkTS语法(声明式UI)-学习ArkTS语言-开发基础知识-入门-HarmonyOS应用开发
开发入门
第三方库
应用模型
HarmonyOS先后提供了两种应用模型:
- FA(Feature Ability)模型: HarmonyOS API 7开始支持的模型,已经不再主推。FA模型开发可见FA模型开发概述。 [[FA模型]]
- Stage模型: HarmonyOS API 9开始新增的模型,是目前主推且会长期演进的模型。在该模型中,由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”,因此称这种应用模型为Stage模型。Stage模型开发可见Stage模型开发概述。
json和json5文件
JSON(JavaScript Object Notation)和JSON5(JSON for humans)都是用于数据交换的文本格式,它们具有相似的语法和结构,但也有一些明显的区别。
- 语法支持:JSON5相对于JSON具有更宽松的语法规则。JSON5允许使用JavaScript风格的注释(包括单行注释和多行注释)、无引号的属性名、单引号的字符串等。而JSON要求属性名和字符串必须使用双引号包裹,并且不支持注释。
- 数据类型支持:JSON5在数据类型上相对于JSON有一些扩展。JSON5支持Infinity、NaN、日期对象(Date)、正则表达式(RegExp)等数据类型,而JSON标准只支持null、布尔值、数字、字符串、数组和对象。
- 尾逗号支持:JSON5允许在对象和数组的最后一个元素后面添加逗号,而JSON不允许这样做。例如,在JSON5中可以写成
[1, 2, 3,]
,而在JSON中必须写成[1, 2, 3]
。 - 键名支持:JSON5允许使用无引号的键名,这在某些场景下可以提高可读性。例如,在JSON5中可以写成
{ key: "value" }
,而在JSON中必须写成{ "key": "value" }
。
需要注意的是,尽管JSON5的语法相对宽松,但它并不是JSON的超集。这意味着,符合JSON5规则的文本可能无法被所有的JSON解析器正确解析。因此,在选择使用JSON或JSON5时,需要考虑目标平台和解析器的兼容性。
总而言之,JSON5是对JSON的一种扩展,提供了更灵活和人性化的语法规则,以便于人们编写和阅读。它在某些场景下可能更适合使用,特别是在需要与JavaScript代码紧密集成的情况下。
目录
==HAP 相当于Moudle,Entry相当于入口==
- HAP(HarmonyOS Ability Package):这是一个包含应用程序代码、资源文件和应用程序清单的文件。它被用作部署和安装在鸿蒙设备上的应用程序。
- Entry类型的HAP:是应用的主模块,在module.json5配置文件中的type标签配置为“entry”类型。在同一个应用中,==同一设备类型只支持一个Entry类型的HAP==,通常用于实现应用的入口界面、入口图标、主特性功能等。
- Ability:在鸿蒙系统中,Ability分为两种类型,一种是Service Ability(服务能力),另一种是Page Ability(页面能力)。前者主要处理后台任务,如数据获取等;后者则负责提供用户界面并与用户进行交互。
AppScope > app.json5:应用的全局配置信息。
entry:HarmonyOS工程模块,编译构建生成一个HAP包。
- src > main > ets:用于存放ArkTS源码。
- src > main > ets > entryability:应用/服务的入口。
- src > main > ets > pages:应用/服务包含的页面。
- src > main > resources:用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。关于资源文件,详见资源分类与访问。
- src > main > module.json5:Stage模型模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明,详见module.json5配置文件。
- build-profile.json5:当前的模块信息、编译信息配置项,包括buildOption、targets配置等。其中targets中可配置当前运行环境,默认为HarmonyOS。
- hvigorfile.ts:模块级编译构建任务脚本,开发者可以自定义相关任务和代码实现。
oh_modules:用于存放三方库依赖信息。关于原npm工程适配ohpm操作,请参考历史工程迁移。
build-profile.json5:应用级配置信息,包括签名、产品配置等。
hvigorfile.ts:应用级编译构建任务脚本。
开发者也可以在右键点击“pages”文件夹时,选择“New > Page”,则无需手动配置相关页面路由。
UIAbility
UIAbility组件生命周期-UIAbility组件-Stage模型应用组件-Stage模型开发指导-应用模型-开发 | 华为开发者联盟
UIAbility 相当于Android Activity,一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务。
在鸿蒙操作系统(HarmonyOS)中,UIAbility和Page是两个不同的概念,它们都属于应用程序的组成部分,但在功能和使用上有所区别。
- UIAbility:UIAbility是HarmonyOS中处理用户界面相关任务的能力(Ability),它继承自基础类Ability。一个UIAbility可以包含多个Page。UIability主要负责页面导航、数据传递以及生命周期管理等。
- Page:Page是构成UIAbility的基本单元,你可以将其理解为一种界面布局。一个页面通常代表了一个完整的用户界面,并且可以包含许多控件(Components)。每个Page都有自己独立的生命周期,并且在需要时可以被创建、暂停或销毁。
简单来说,你可以把UIAbility看作是一本书,而每个Page就像书中的一页。同时,这两者共同工作以提供流畅且连贯的用户体验。
生命周期
WindowStageCreate和WindowStageDestroy状态
UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,可以在该回调中设置UI界面加载、设置WindowStage的事件订阅。
1 |
|
启动模式
UIAbility组件启动模式-UIAbility组件-Stage模型应用组件-Stage模型开发指导-应用模型-开发 | 华为开发者联盟
singleton:==单实例模式,也是默认情况下的启动模式==。在最近任务列表中只存在一个该类型的UIAbility实例。
multiton:标准实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。
specified:启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
与UI的数据同步
UIAbility组件与UI的数据同步-UIAbility组件-Stage模型应用组件-Stage模型开发指导-应用模型-开发 | 华为开发者联盟
基于HarmonyOS的应用模型,可以通过以下两种方式来实现UIAbility组件与UI之间的数据同步。
- EventHub:基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。
- globalThis:ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。