提示:本文根据b站尚硅谷2024最新鸿蒙开发HarmonyOS4.0+鸿蒙NEXT星河版零基础教程课整理
链接指引 => 尚硅谷2024最新鸿蒙开发HarmonyOS4.0+鸿蒙NEXT星河版零基础教程
一、ArkTS
ArkTS 在继承了Typescript语法的基础上,主要扩展了声明式UI开发相关的能力。
1、声明式UI
按照声明式UI的开发范式,首先需要分析和定义页面的各种状态,并声明相应的状态变量用于表示不同的状态。
开关灯案例
@Entry
@Component
struct LightPage {
@State isOn: boolean = false;
build() {
Column({ space: 20 }) {
if (this.isOn) {
Image('pages/helloworld/light/solution/images/img_light.png')
.height(300)
.width(300)
.borderRadius(20)
} else {
Image('pages/helloworld/light/solution/images/img_dark.png')
.height(300)
.width(300)
.borderRadius(20)
}
Row({ space: 50 }) {
Button('关灯')
.onClick(() => {
this.isOn = false
})
Button('开灯')
.onClick(() => {
this.isOn = true;
})
}
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
2、声明组件
声明组件的完整语法如下图所示
2.1 组件参数
如果组件的定义包含参数,可在组件名称后面的()中配置相应参数。各组件支持的参数,可查看 API 文档,查看方式如下
2.2 子组件
如果组件支持子组件配置,可在()后的{}中添加子组件,若不支持子组件,则不需要写{}。
2.3 属性方法
属性方法用于配置组件的样式和其他属性,可以在组件声明的末尾进行链式调用。各组件支持的属性可查看 API 文档,除去每个组件的专有属性,还有各组件都能配置的通用属性,通用属性也可通过 API 文档查看。
2.4 事件方法
事件方法用于为组件绑定交互事件,可以在组件声明的末尾进行链式调用。各组件的支持的事件可查看 API 文档,除去每个组件的专有事件,还有各组件都支持的通用事件,通用事件也可通过 API 文档查看。
2.5 自定义组件
除去系统预置的组件外,ArkTS 还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性
自定义组件的语法如下图所示
各部分语法说明如下:
● struct
关键字struct
是ArkTS
新增的用于自定义组件或者自定义弹窗的关键字。其声明的数据结构和TS
中的类十分相似,可包含属性和方法。
● build
方法build()
方法用于声明自定义组件的UI结构。
● 组件属性
组件属性可用作自定义组件的参数,使得自定义组件更为通用。
● @Compnent
装饰器@Component
装饰器用于装饰struct
关键字声明的数据结构。struct
被@Component
装饰后才具备组件化的能力。
注: 装饰器是Typescript
中的一种特殊语法,常用于装饰类、方法、属性,用于修改或扩展其原有的行为。
例子:
@Entry
@Component
struct HelloWorldPage {
@State isOn: boolean = false;
build() {
Column({ space: 20 }) {
if (this.isOn) {
Image('pages/helloworld/custom/solution/images/img_light.png')
.height(300)
.width(300)
.borderRadius(20)
} else {
Image('pages/helloworld/custom/solution/images/img_dark.png')
.height(300)
.width(300)
.borderRadius(20)
}
Row({ space: 50 }) {
SwitchButton({ color: Color.Red })
.onClick(() => {
this.isOn = false
})
SwitchButton({ color: Color.Green })
.onClick(() => {
this.isOn = true;
})
}
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
@Component
struct SwitchButton {
color: Color = Color.Blue;
build() {
Button({ type: ButtonType.Circle }) {
Image('pages/helloworld/custom/solution/images/icon_switch.png')
.width(30)
.width(30)
}.width(50)
.height(50)
.backgroundColor(this.color)
}
}
3、渲染控制
3.1 条件渲染
语法说明
if (...){
//UI描述
}else if (...){
//UI描述
}else{
//UI描述
}
3.2 循环渲染
ForEach
循环渲染的语法如下
ForEach(
arr: any[],
itemGenerator: (item: any, index?: number) => void,
keyGenerator?: (item: any, index?: number) => string
)
各参数的含义如下
arr
需要进行循环渲染的数据源,必须为数组类型,例如上述案例中的@State options: string[] = ["苹果", "桃子", "香蕉", "橘子"];
itemGenerator
组件生成函数,用于为arr数组中的每个元素创建对应的组件。该函数可接收两个参数,分别是- item:
arr
数组中的数据项 index(可选):
arr
数组中的数据项的索引
例如上述案例中的(item: string) => { Button(item) .width(100) .backgroundColor(Color.Green) .onClick(() => { this.answer = item; }) }
- item:
- keyGenerator(可选):
key
生成函数,用于为arr数组中的每个数据项生成唯一的key
。
key的作用
> `ForEach`在数组发生变化(修改数组元素或者向数组增加或删除元素)时,需要重新渲染组件列表,在重新渲染时,它会尽量复用原来的组件对象,而不是为每个元素都重新创建组件对象。`key`的作用就是辅助`ForEach`完成组件对象的复用。
具体逻辑如下:
`ForEach`在进行初次渲染时,会使用`keyGenerator`为数组中的每个元素生成一个唯一的key,并将key作为组件对象的标识。当数组发生变化导致`ForEach`需要重新渲染时,`ForEach`会再次使用`keyGenerator`为每个元素重新生成一遍key,然后`ForEach`会检查新生成的key在上次渲染时是否已经存在,若存在,`ForEach`就会认为这个`key`对应的数组元素没有发生变化,那它就会直接复用这个key所对应的组件对象;若不存在,`ForEach`就会认为这个`key`对应的元素发生了变化,或者该元素为新增元素,此时,就会为该元素重新创建一个组件对象。
开发者可以通过`keyGenerator`函数自定义key的生成规则。如果开发者没有定义`keyGenerato`r函数,则系统会使用默认的`key`生成函数,即
```ts
(item: any, index: number) => { return index + '__' + JSON.stringify(item); }
```
在某些情况下默认的key生成函数,会导致界面渲染效率低下,此时可考虑通过keyGenerator函数自定义生成逻辑,例如如下场景
状态变量数组定义如下
@State arr:string[] = ["zhangsan","lisi","wangwu"]
ForEach语句如下
```ts
Column(){
ForEach(this.arr,(item)=>{ Text(item) })
}
```
初次渲染时,每个元素对应的`key`依次为`0__"zhagnsan"`、`1__"lisi"`、`2__"wangwu"`。若现有一个操作是向`arr`数组头部插入新的元素,例如新元素为`wanger`,按照默认的key生成逻辑,插入新元素之后每个元素的key就会依次变为`0__"wanger"`、`1__"zhagnsan"`、`2__"lisi"`、`3__"wangwu"`,也就是所有元素的`key`都发生了变化,因此UI界面更新时需要为每个元素都重新创建组件对象,即便原有的元素没有发生变化也无法复用之前的组件,这样一来就导致了性能浪费。此时我们就可以考虑提供第三个参数,如下
```ts
Column(){
ForEach(this.arr, (item)=>{ Text(item) }, item => JSON.stringify(item))
}
```
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。