@Builder装饰器:自定义构建函数
被@Builder装饰的函数称为自定义构建函数 ,它是一种轻量化 UI 复用机制,它允许开发者将重复使用的 UI 元素抽象为函数,这些函数可以在 build 函数中被调用以实现 UI 复用。
自定义构建函数根据定义的位置不同分为私有自定义函数 和全局自定义函数。
私有自定义构建函数
私有自定义构建函数定义在@Component组件内,属于该组件私有的,只能在该组件内 的build函数或者其他自定义构建函数中调用。
ts{9-12,5}
@Component
struct MyComponent {
build() {
Column() {
this.myBuilder()
}
}
@Builder
myBuilder() {
Text("私有@Builder")
}
}
@Entry
@Component
struct Index {
build() {
Column({ space: 10 }) {
MyComponent()
}
.width("100%")
.height("100%")
}
}
全局自定义构建函数
全局自定义函数定义在@Component组件外,可以在其他自定义函数或者其他自定义组件中调用。
ts{1-4,11}
@Builder
function myBuilder() {
Text("全局@Builder")
}
@Entry
@Component
struct Index {
build() {
Column({ space: 10 }) {
myBuilder()
}
.width("100%")
.height("100%")
}
}
@Builder与@Component的区别
经过上面的描述可能会发现@Component和@Builder都可以用于UI复用,他们的区别如下:
@Builder:纯UI逻辑复用,无独立状态管理与生命周期,必须通过参数传递的方式与调用方完成数据交互。@Component:完整组件封装,拥有独立状态管理与生命周期。
自定义构建函数参数传递规则
自定义构建函数的参数传递有按值传递 和按引用传递两种,均需遵守以下规则:
- 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
- 在
@Builder装饰的函数内部,不允许改变参数值。 - 只有当传入一个参数且该参数直接传入对象字面量时,才会按引用传递,其他传递方式均为按值传递。
按值传递参数
定义一个全局自定义构建函数textBuilder(text: string),参数只有一个且不是字面量对象,所以按照值传递。
ts
@Builder
function textBuilder(text: string) {
Text("Hello,"+text).fontSize(30)
}
调用@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起@Builder函数内的UI刷新
ts
@Entry
@Component
struct Index {
@State text: string = 'World'
build() {
Column() {
textBuilder(this.text)
Button("修改text").onClick(() => {
//修改状态变量,不会引用@Builder函数中UI的更新
this.text = "ArkUI"
})
}
}
}
如下图,经测试状态变量的改变不会引起@Builder函数内UI刷新

按引用传递参数
定义一个@Builder自定义构建函数,参数为自定义对象类型。
ts
class Params {
text: string = ''
}
@Builder
function textBuilder(params: Params) {
Text(`Hello, ${params.text}`).fontSize(30)
}
调用按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder函数内的UI刷新。
ts
@Entry
@Component
struct Index {
@State text: string = 'World'
build() {
Column() {
textBuilder({
text: this.text
})
Button("修改text").onClick(() => {
//修改状态变量,不会引用@Builder函数中UI的更新
this.text = "ArkUI"
})
}
}
}
预览效果如下图所示:

限制条件
@Builder自定义函数内部不允许修改参数值,否则框架会抛出运行时异常。@Builder自定义构建函数存在两个或两个以上的参数时,即使通过对象字面量形式传递,值的改变也不会触发UI刷新。
示例1:在@Builder中修改参数值
ts
class Params {
text: string = ''
}
@Builder
function textBuilder(params: Params) {
Text(`Hello, ${params.text}`).fontSize(30)
.onClick(() => {
params.text = "哈哈哈" //【错误】,禁止改参数的值
})
}
如下图所示,出现预览错误

示例2:在@Builder中接收两个参数,不会触发UI更新。
ts
import { promptAction } from "@kit.ArkUI"
class Params {
text: string = ''
}
@Builder
function textBuilder(params: Params,num:number) {
Column(){
Text(`Hello, ${params.text}`).fontSize(30)
.onClick(() => {
params.text = "哈哈哈"
})
Text(`${num}`)
}
}
@Entry
@Component
struct Index {
@State text: string = 'World'
build() {
Column() {
textBuilder({
text: this.text
},100)
Button("修改text").onClick(() => {
//修改状态变量,不会引用@Builder函数中UI的更新
this.text = "ArkUI"
})
}
}
}
如下图,当@Builder接收2个参数时,UI更新不生效。
对鸿蒙感兴趣的同学,免费考取鸿蒙开发者认证