提示:本文根据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关键字
structArkTS新增的用于自定义组件或者自定义弹窗的关键字。其声明的数据结构和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;
            })
        }
  • 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))
}
```

玲小叮当
86 声望12 粉丝

一名前端人儿的笔记,欢迎来到这里,希望这里的文章对你有所帮助!