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