赞
踩
当页面有多个相同的UI结构时,若每个都单独声明,同样会有大量重复的代码。为避免重复代码,可以将相同的UI结构提炼为一个自定义组件
,完成UI结构的复用。
除此之外,ArkTS
还提供了一种更轻量的UI结构复用机制@Builder
方法,开发者可以将重复使用的UI元素抽象成一个@Builder
方法,该方法可在build()
方法中调用多次,以完成UI结构的复用。
@Builder
方法同样可以定义在组件内或者全局,具体语法如下
● 组件内
@Entry @Component struct BuilderPage { build() { Column() { Row({ space: 50 }) { //复用UI结构 this.compButtonBuilder($r('app.media.icon_edit'), '编辑', () => console.log('编辑')) this.compButtonBuilder($r('app.media.icon_send'), '发送', () => console.log('发送')) } }.width('100%') .height('100%') .justifyContent(FlexAlign.Center) } //定义UI结构 @Builder compButtonBuilder(icon: Resource, text: string, callback: () => void) { Button() { Row({ space: 10 }) { Image(icon) .width(25) .height(25) Text(text) .fontColor(Color.White) .fontSize(25) } }.width(120) .height(50) .onClick(callback) } }
● 全局
@Entry @Component struct BuilderPage { build() { Column() { Row({ space: 50 }) { //复用UI结构 globalButtonBuilder($r('app.media.icon_edit'), '编辑', () => console.log('编辑')) globalButtonBuilder($r('app.media.icon_send'), '发送', () => console.log('发送')) } }.width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } //定义UI结构 @Builder function globalButtonBuilder(icon: Resource, text: string, callback: () => void) { Button() { Row({ space: 10 }) { Image(icon) .width(25) .height(25) Text(text) .fontColor(Color.White) .fontSize(25) } }.width(120) .height(50) .onClick(callback) }
@Builder
方法可通过this
访问当前组件的属性和方法,而全局的@Builder
方法则不能@Builder
方法只能用于当前组件,全局的@Builder
方法导出(export)
后,可用于整个应用。@Builder
方法参数传递规则@Builder
方法具有两种参数传递机制——按值传递
和按引用传递
。当只有一个参数且参数为对象字面量
时为按引用传递,其余情况均为按值传递。
按引用传递时,若传递的参数为状态变量,则状态变量的变化将会触发@Builder
方法内部UI的刷新;按值传递时则不会。
@Entry @Component struct BuilderParameterPage { @State count: number = 0; build() { Column({ space: 50 }) { //按值传递 valueTextBuilder(this.count) //按引用传递 referenceTextBuilder({ count: this.count }) Row({ space: 50 }) { Button('-1').onClick(() => { this.count--; }) Button('+1').onClick(() => { this.count++; }) } }.width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } @Builder function valueTextBuilder(count: number) { Text(`按值传递: ${count}`) .fontSize(30) .fontWeight(FontWeight.Bold) } @Builder function referenceTextBuilder(obj: { count: number }) { Text(`按引用传递: ${obj.count}`) .fontSize(30) .fontWeight(FontWeight.Bold) }
@Builder
方法和自定义组件的区别@Builder
方法和自定义组件虽然都可以实现UI复用的效果,但是两者还是有着本质的区别的,其中最为显著的一个区别就是自定义组件可以定义自己的状态变量,而@Builder
方法则不能。
以下案例中,每个待办事项的UI结构都相同,因此可考虑将其提炼为一个自定义组件或者@Builder
方法,但是由于每个待办事项均有已完成
和未完成
两种状态,因此需要为每个待办事项都定义一个状态变量,所以此时就只能使用自定义组件而不能使用@Builder
方法。
若复用的UI结构没有状态,推荐使用@Builder
方法,否则使用自定义组件。
@BuilderParam
@BuilderParam
用于装饰自定义组件(struct
)中的属性,其装饰的属性可作为一个UI结构的占位符
,待创建该组件时,可通过参数为其传入具体的内容。(其作用类似于Vue
框架中的slot
)。
例如
定义一个组件,使用@BuilderParam
占位
@Component
struct Container {
//@BuilderParam属性
@BuilderParam content: () => void
build() {
Column() {
Text('其他内容') //其他内容
this.content(); //占位符
Button('其他内容') //其他内容
}
}
}
定义UI结构
@Builder function contentBuilder1() {
...
}
@Builder function contentBuilder2() {
...
}
@Builder function contentBuilder3() {
...
}
组件创建时可传入不同的UI来填充
Container({ content: contentBuilder1 })
Container({ content: contentBuilder2 })
Container({ content: contentBuilder3 })
另外,如果一个组件中只定义了一个@BuilderParam
属性,那么创建该组件时,也可直接通过"子组件"的方式传入具体的UI结构,例如
@Entry @Component struct BuilderParamPage { build() { Column({ space: 50 }) { //创建卡片组件(传参) Card({ content: imageBuilder }) //创建卡片组件("子组件") Card() { Column({ space: 10 }) { Text('鸿蒙操作系统') .fontSize(25) .fontWeight(FontWeight.Bold) Text('鸿蒙操作系统是一款由华为公司开发的多设备统一操作系统,致力于实现无缝连接和协同工作。其采用分布式架构,支持多终端智能互联,提供高效、安全、流畅的用户体验。') } } }.width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } //卡片内容 @Builder function imageBuilder() { Column({ space: 10 }) { Image($r('app.media.img_harmony')) .width(300) .height(150) Text('鸿蒙操作系统') } } //卡片组件 @Component struct Card { @BuilderParam content: () => void; //@BuilderParam属性 build() { Column() { this.content(); //占位符 }.width('90%') .padding(10) .borderRadius(10) .shadow({ radius: 20 }) } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。