概述
当页面有多个相同的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 })
}
}
发表评论