一、鴻蒙開發-ArkTS快速入門

玲小叮当發表於2024-11-10

提示:本文根據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))
}
```

相關文章