HarmonyOS应用开发-@Builder装饰器详解

前言

前面章节介绍了如何创建一个自定义组件。该自定义组件内部UI结构固定,仅与使用方进行数据传递。ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。

装饰器使用说明

自定义组件内自定义构建函数

定义的语法

@Builder myBuilderFunc({ })

调用方法

this.myBuilderFunc()

●允许在自定义组件内定义一个或多个自定义构建函数,该函数被认为是该组件的私有、特殊类型的成员函数。
●自定义构建函数可以在所属组件的build方法和其他自定义构建函数中调用,但不允许在组件外调用。
●在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。

全局自定义构建函数

定义的语法

@Builder function myGlobalBuilderFunc({ })

调用方法

myGlobalBuilderFunc()

●全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。
●如果不涉及组件状态变化,建议使用全局的自定义构建方法。

参数传递规则

自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:

●参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefine

<think> 我们正在讨论的是ArkTS中的@Builder装饰器,用于自定义构建函数。根据引用内容,我们可以总结如下: 1. @Builder装饰器用于创建自定义构建函数,可以将重复的UI结构抽象成一个方法。 2. @Builder装饰的函数遵循build()函数的语法规则。 3. @Builder有两种类型:自定义组件内定义的私有@Builder(只能在组件内调用)和全局的@Builder(可以在整个应用内调用)。 4. 参数传递方式:默认按值传递,但为了在传递状态变量时能够触发UI刷新,推荐使用按引用传递(使用'$'符号)。 下面将详细介绍使用方法,包括基本使用、参数传递、在组件内定义和全局定义等。 ### 1. 基本使用方法 #### 1.1 组件内私有@Builder 在自定义组件内使用`@Builder`装饰一个函数,该函数可以在组件的build函数或其他自定义构建函数中调用。 ```typescript @Entry @Component struct MyComponent { @Builder myBuilderFunction() { // 在这里构建UI Column() { Text('Hello, Builder!') .fontSize(20) Button('Click me') .onClick(() => { // 点击事件 }) } } build() { Column() { // 调用自定义构建函数 this.myBuilderFunction() } } } ``` #### 1.2 全局@Builder 在组件外定义的@Builder函数是全局的,可以在任意组件中调用。 ```typescript // 全局自定义构建函数 @Builder function GlobalBuilder() { Row() { Text('Global Builder') .fontColor(Color.Blue) } } @Entry @Component struct MyComponent { build() { Column() { // 调用全局构建函数 GlobalBuilder() } } } ``` ### 2. 参数传递 #### 2.1 按值传递(默认) 默认情况下,@Builder函数的参数是按值传递的。这意味着当传递的状态变量发生变化时,不会触发@Builder函数内部的UI刷新。 ```typescript @Builder function ValueTransferBuilder(paramA: string) { Row() { Text(`参数值: ${paramA}`) } } @Entry @Component struct ParentComponent { @State message: string = '初始值' build() { Column() { // 按值传递,message的变化不会触发Builder内部更新 ValueTransferBuilder(this.message) Button('改变值').onClick(() => { this.message = '新值' }) } } } ``` 点击按钮后,虽然`message`状态改变了,但`ValueTransferBuilder`中显示的文本不会更新。 #### 2.2 按引用传递 为了能够响应状态变化,需要使用按引用传递,在参数名前加上`$`符号。 ```typescript @Builder function ReferenceTransferBuilder($paramA: string) { Row() { Text(`参数值: ${$paramA}`) // 当paramA变化时,这里会更新 } } @Entry @Component struct ParentComponent { @State message: string = '初始值' build() { Column() { // 按引用传递,message变化会触发Builder内部更新 ReferenceTransferBuilder($$this.message) Button('改变值').onClick(() => { this.message = '新值' }) } } } ``` 注意:在调用时,我们使用`$$`来传递状态变量的引用(在ArkTS中,按引用传递的语法是`$$变量名`)。这样,当状态变量`message`改变时,构建函数内部也会更新。 ### 3. 在@Builder中访问组件状态 在组件内的@Builder函数中,可以直接通过`this`访问组件的状态变量。 ```typescript @Entry @Component struct MyComponent { @State count: number = 0 @Builder CounterBuilder() { // 直接使用this.count访问组件的状态变量 Button(`点击次数: ${this.count}`) .onClick(() => { this.count++ // 修改状态,会触发UI更新 }) } build() { Column() { this.CounterBuilder() } } } ``` ### 4. 组合使用多个@Builder 自定义构建函数可以相互调用,实现更复杂的UI复用。 ```typescript @Entry @Component struct MyComponent { @Builder HeaderBuilder(title: string) { Text(title) .fontSize(30) .fontWeight(FontWeight.Bold) } @Builder FooterBuilder() { Text('底部信息') .fontSize(14) .fontColor(Color.Gray) } @Builder ContentBuilder() { Column() { this.HeaderBuilder('主标题') Text('这里是内容区域...') this.FooterBuilder() } } build() { Column() { this.ContentBuilder() } } } ``` ### 总结 使用@Builder装饰器可以有效地复用UI代码,提高开发效率。关键点包括: - 私有@Builder在组件内定义,全局@Builder在组件外定义。 - 默认按值传递参数,若希望响应状态变化,需使用按引用传递(在参数前加`$`,并使用`$$`传递状态变量)。 - 在组件内的@Builder中,可以通过`this`访问组件的状态变量。 通过合理使用@Builder,可以构建出结构清晰、易于维护的UI代码。 [^1]: HarmonyOS开发者文档中心 - ArkTS @Builder装饰器 [^2]: OpenHarmony实战——自定义构建函数:@Builder装饰器 [^3]: ArkTS @Builder装饰器:自定义构建函数 [^4]: 构建ArkTS之@Builder装饰器:自定义构建函数 §§相关问题§§ 1. 如何理解ArkTS中@Builder装饰器的按引用传递? 2. 全局@Builder和组件内@Builder有什么区别? 3. 在@Builder中如何访问外部组件的状态变量? 4. @Builder装饰器与自定义组件有何异同? 5. 如何避免在@Builder中产生不必要的UI刷新? </think>### @Builder装饰器的使用方法详解 @Builder是ArkUI提供的轻量级UI元素复用机制,用于创建可复用的UI构建函数。以下是具体使用方法: #### 1. **基本定义语法** ```typescript // 组件内私有构建函数 @Builder myBuilder() { // UI结构 } // 全局构建函数 @Builder function GlobalBuilder() { // UI结构 } ``` #### 2. **组件内私有构建函数** 在自定义组件内部使用,通过`this`访问组件状态: ```typescript @Component struct MyComponent { @State counter: number = 0 // 私有构建函数 @Builder CounterButton() { Button(`点击 ${this.counter}`) .onClick(() => this.counter++) .margin(10) } build() { Column() { this.CounterButton() // 调用构建函数 this.CounterButton() // 复用UI } } } ``` #### 3. **全局构建函数** 定义在组件外部,可在任意组件中调用: ```typescript // 全局构建函数[^2] @Builder function RedButton(label: string) { Button(label) .backgroundColor(Color.Red) .fontColor(Color.White) } @Entry @Component struct HomePage { build() { Column() { RedButton('警告') // 全局调用 RedButton('危险') } } } ``` #### 4. **参数传递方式** - **按值传递**(默认):状态变量更新不会触发UI刷新 ```typescript @Builder function StaticBuilder(param: string) { Text(param) // 不会响应外部变化 } ``` - **按引用传递**(推荐):使用`$`前缀响应状态变化[^3] ```typescript @Builder function DynamicBuilder($param: string) { Text($param) // 响应外部状态变化 } // 调用时 DynamicBuilder($$this.stateVar) ``` #### 5. **最佳实践** 1. **访问组件状态**:在私有构建函数中直接通过`this`访问 ```typescript @Builder ThemeButton() { Button(this.buttonText) // 直接访问组件状态 .backgroundColor(this.themeColor) } ``` 2. **组合使用**:构建函数可嵌套调用 ```typescript @Builder FormItem(label: string) { Row() { Text(label).width('30%') RedButton('提交') // 调用其他构建函数 } } ``` 3. **样式分离**:与@Styles配合使用 ```typescript @Styles function cardStyle() { .padding(10) .backgroundColor(Color.White) } @Builder function InfoCard() { Column() { // 内容 }.style(cardStyle) // 应用样式 } ``` #### 6. **与自定义组件的区别** | 特性 | @Builder构建函数 | 自定义组件 | |--------------|-----------------------|-------------------| | 复用粒度 | UI片段 | 完整组件 | | 状态管理 | 依赖父组件状态 | 自有状态管理 | | 生命周期 | 无 | 完整生命周期 | | 参数传递 | 灵活的直接参数传递 | 通过属性参数传递 | | 最佳场景 | 简单UI复用 | 复杂独立功能模块 | [^1]: HarmonyOS开发者文档中心 - @Builder装饰器 [^2]: OpenHarmony实战 - 自定义构建函数 [^3]: ArkTS @Builder参数传递规范 [^4]: 构建ArkTS之@Builder装饰器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值