在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。
自定义组件具有以下特点:
-
可组合:允许开发者组合使用系统组件、及其属性和方法。
-
可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
-
数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。
@Component
struct HelloComponent {
@State message: string = '一起修仙呀!';
build() {
// HelloComponent自定义组件组合系统组件Row和Text
Row() {
Text(this.message)
.onClick(() => {
// 状态变量message的改变驱动UI刷新,UI从'一起修仙呀!'刷新为'我是菩提!'
this.message = '我是菩提!';
})
}
}
}
注意
如果在另外的文件中引用该自定义组件,需要使用export关键字导出,并在使用的页面import该自定义组件。
自定义组件的基本结构
-
struct:自定义组件基于struct实现,struct + 自定义组件名 + {...}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。
说明
自定义组件名、类名、函数名不能和系统组件名相同。
-
@Component:@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述UI,一个struct只能被一个@Component装饰。@Component可以接受一个可选的bool类型参数。
说明
从API version 9开始,该装饰器支持在ArkTS卡片中使用。
从API version 11开始,@Component可以接受一个可选的bool类型参数。
-
@Component struct MyComponent { }
build()函数:build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。
-
@Component struct MyComponent { build() { } }
@Entry:@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。@Entry可以接受一个可选的LocalStorage的参数。
说明
从API version 9开始,该装饰器支持在ArkTS卡片中使用。
从API version 10开始,@Entry可以接受一个可选的LocalStorage的参数或者一个可选的EntryOptions参数。
-
@Entry({ routeName : 'myPage' }) @Component struct MyComponent { }
@Reusable:@Reusable装饰的自定义组件具备可复用能力
-
@Component struct MyComponent { private countDownFrom: number = 0; private color: Color = Color.Blue; build() { } } @Entry @Component struct ParentComponent { private someColor: Color = Color.Pink; build() { Column() { // 创建MyComponent实例,并将创建MyComponent成员变量countDownFrom初始化为10,将成员变量color初始化为this.someColor MyComponent({ countDownFrom: 10, color: this.someColor }) } } }
build()函数
所有声明在build()函数的语句,我们统称为UI描述,UI描述需要遵循以下规则:
-
@Entry装饰的自定义组件,其build()函数下的根节点唯一且必要,且必须为容器组件,其中ForEach禁止作为根节点。
@Component装饰的自定义组件,其build()函数下的根节点唯一且必要,可以为非容器组件,其中ForEach禁止作为根节点。
-
@Entry @Component struct MyComponent { build() { // 根节点可为空,必须为容器组件 Row() { ChildComponent() } } } @Component struct ChildComponent { build() { // 根节点可为空,可为非容器组件 Image('test.jpg') } }
不允许调用没有用@Builder装饰的方法,允许系统组件的参数是TS方法的返回值。
-
@Component struct ParentComponent { doSomeCalculations() { } calcTextValue(): string { return 'Hello World'; } @Builder doSomeRender() { Text(`Hello World`) } build() { Column() { // 反例:不能调用没有用@Builder装饰的方法 this.doSomeCalculations(); // 正例:可以调用 this.doSomeRender(); // 正例:参数可以为调用TS方法的返回值 Text(this.calcTextValue()) } } }