鴻蒙:自定義組件
@Component
struct HelloComponent {
@State message: string = 'Hello, World!';
build() {
// HelloComponent自定義組件組合系統(tǒng)組件Row和Text
Row() {
Text(this.message)
.onClick(() => {
// 狀態(tài)變量message的改變驅(qū)動UI刷新矾麻,UI從'Hello, World!'刷新為'Hello, ArkUI!'
this.message = 'Hello, ArkUI!';
})
}
}
}
class HelloComponentParam {
message: string = ""
}
@Entry
@Component
struct ParentComponent {
param: HelloComponentParam = {
message: 'Hello, World!'
}
build() {
Column() {
Text('ArkUI message')
HelloComponent(this.param);
Divider()
HelloComponent(this.param);
}
}
}
1.自定義組件的基本結(jié)構(gòu)
- @Entry:@Entry裝飾的自定義組件將作為UI頁面的入口。
- struct:自定義組件基于struct實現(xiàn),struct + 自定義組件名 + {...}的組合構(gòu)成自定義組件霜运,不能有繼承關(guān)系勾邦。對于struct的實例化,可以省略new午衰。
- @Component:@Component裝飾器僅能裝飾struct關(guān)鍵字聲明的數(shù)據(jù)結(jié)構(gòu)立宜,struct被@Component裝飾后具備組件化的能力,需要實現(xiàn)build方法描述UI
- build()函數(shù):build()函數(shù)用于定義自定義組件的聲明式UI描述臊岸,自定義組件必須定義build()函數(shù)橙数。
- @Reusable:@Reusable裝飾的自定義組件具備可復用能力
@Entry({ routeName : 'myPage' })
@Reusable
@Component
struct MyComponent {
build() {
}
}
2.成員函數(shù)/變量
自定義組件的成員函數(shù)為私有的,且不建議聲明成靜態(tài)函數(shù)帅戒。
下面的示例代碼將父組件中的函數(shù)傳遞給子組件灯帮,并在子組件中調(diào)用。
@Entry
@Component
struct Parent {
@State cnt: number = 0
submit: () => void = () => {
this.cnt++;
}
build() {
Column() {
Text(`${this.cnt}`)
Son({ submitArrow: this.submit })
}
}
}
@Component
struct Son {
submitArrow?: () => void
build() {
Row() {
Button('add')
.width(80)
.onClick(() => {
if (this.submitArrow) {
this.submitArrow()
}
})
}
.justifyContent(FlexAlign.SpaceBetween)
.height(56)
}
}
3.build()函數(shù)
所有聲明在build()函數(shù)的語句蜘澜,我們統(tǒng)稱為UI描述施流,UI描述需要遵循以下規(guī)則:
- @Entry裝飾的自定義組件,其build()函數(shù)下的根節(jié)點唯一且必要鄙信,且必須為容器組件瞪醋,其中ForEach禁止作為根節(jié)點。
- @Component裝飾的自定義組件装诡,其build()函數(shù)下的根節(jié)點唯一且必要银受,可以為非容器組件,其中ForEach禁止作為根節(jié)點鸦采。
@Entry
@Component
struct MyComponent {
build() {
// 根節(jié)點唯一且必要宾巍,必須為容器組件
Row() {
ChildComponent()
}
}
}
@Component
struct ChildComponent {
build() {
// 根節(jié)點唯一且必要,可為非容器組件
Image('test.jpg')
}
}
- 不允許聲明本地變量渔伯,反例如下顶霞。
- 不允許在UI描述里直接使用console.info,但允許在方法或者函數(shù)里使用锣吼,反例如下
- 不允許創(chuàng)建本地的作用域选浑,反例如下。
- 不允許調(diào)用沒有用@Builder裝飾的方法玄叠,允許系統(tǒng)組件的參數(shù)是TS方法的返回值古徒。
- 不允許使用switch語法,如果需要使用條件判斷读恃,請使用if隧膘。示例如下代态。
- 不允許使用表達式,反例如下疹吃。
- 不允許直接改變狀態(tài)變量蹦疑,會造成循環(huán)渲染的風險。
build() {
// 反例1:不允許聲明本地變量
let a: number = 1;
// 反例2:不允許console.info
console.info('print debug log');
// 反例3:不允許本地作用域
{
...
}
}
@Component
struct ParentComponent {
@State count: number = 1;
doSomeCalculations() {
}
calcTextValue(): string {
return 'Hello World';
}
@Builder doSomeRender() {
Text(`Hello World`)
}
build() {
Column() {
// 反例4:不能調(diào)用沒有用@Builder裝飾的方法
this.doSomeCalculations();
// 正例:可以調(diào)用
this.doSomeRender();
// 正例:參數(shù)可以為調(diào)用TS方法的返回值
Text(this.calcTextValue())
// 反例5:不允許使用switch語法
switch (expression) {
case 1:
Text('...')
break;
case 2:
Image('...')
break;
default:
Text('...')
break;
}
// 正例:使用if
if(expression == 1) {
Text('...')
} else if(expression == 2) {
Image('...')
} else {
Text('...')
}
// 反例6:不允許使用表達式
(this.aVar > 10) ? Text('...') : Image('...')
//反例7: 應避免直接在Text組件內(nèi)改變count的值
Text(`${this.count++}`)
}
// 反例 8:
@State arr : Array<...> = [ ... ];
ForEach(this.arr.sort().filter(...),
item => {
...
})
// 正確的執(zhí)行方式為:filter返回一個新數(shù)組互墓,后面的sort方法才不會改變原數(shù)組this.arr
ForEach(this.arr.filter(...).sort(),
item => {
...
})
}
4.自定義組件通用樣式
- 自定義組件通過“.”鏈式調(diào)用的形式設(shè)置通用樣式必尼。一行一個
@Component
struct MyComponent2 {
build() {
Button(`Hello World`)
}
}
@Entry
@Component
struct MyComponent {
build() {
Row() {
MyComponent2()
.width(200)
.height(300)
.backgroundColor(Color.Red)
}
}
}