一.@Builder,@BuilderParam的简要介绍
1.@Builder装饰器:自定义构建函数
-
允许在自定义组件内定义一个或多个@Builder方法,该方法被认为是该组件的私有、特殊类型的成员函数。
-
自定义构建函数可以在所属组件的build方法和其他自定义构建函数中调用,但不允许在组件外调用。
-
在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。
@Builder可以在组件内定义,也可定义全局自定义构建函数:
/**
*全局定义函数,注意添加function关键字标识
*如果不涉及组件状态变化,建议使用全局的自定义构建方法。
*/
@Builder function MyGlobalBuilderFunction() { ... }
//使用方法
MyGlobalBuilderFunction()
/**
*自定义组件内自定义构建函数
*/
@Builder MyBuilderFunction() { ... }
//使用方法(使用this关键字指向)
this.MyBuilderFunction()
2.@BuilderParam装饰器:引用@Builder函数
开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量(@BuilderParam是用来承接@Builder函数的),开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
/**
*以下示例中,Parent组件在调用this.componentBuilder()时,this指向其所属组件,即“Parent”。*@Builder componentBuilder()通过this.componentBuilder的形式传给子组件@BuilderParam *customBuilderParam,this指向在Child的label,即“Child”。@Builder componentBuilder()
*通过 ():void=>{this.componentBuilder()}的形式传给子组件@BuilderParam *customChangeThisBuilderParam,因为箭头函数的this指向的是宿主对象,所以label的值为“Parent”。
*/
@Component
struct Child {
label: string = `Child`
@Builder customBuilder() {}
@Builder customChangeThisBuilder() {}
@BuilderParam customBuilderParam: () => void = this.customBuilder;
@BuilderParam customChangeThisBuilderParam: () => void = this.customChangeThisBuilder;
build() {
Column() {
//注意加上(),编译器不加()也会通过,但是无法生效。
this.customBuilderParam()
this.customChangeThisBuilderParam()
}
}
}
@Entry
@Component
struct Parent {
label: string = `Parent`
@Builder componentBuilder() {
Text(`${this.label}`)
}
build() {
Column() {
this.componentBuilder()
Child({ customBuilderParam: this.componentBuilder, customChangeThisBuilderParam: ():void=>{this.componentBuilder()} })
}
}
}
二.自定义封装全局通用导航栏
封装:
// NavigationBar.ets
/**
* 自定义通用导航栏
*/
@Component
export struct NavigationBar {
@Prop title: String;
@Builder buttonBack(){}
@Builder menuOne(){}
@Builder menuTwo(){}
@Builder menuThree(){}
@BuilderParam buildButtonBackParam:()=> void = this.buttonBack
@BuilderParam buildMenuOneParam:()=> void = this.menuOne
@BuilderParam buildMenuTwoParam:()=> void = this.menuTwo
@BuilderParam buildMenuThreeParam:()=> void = this.menuThree
build() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
Row() {
this.buildButtonBackParam()
}.margin({left:15})
//水平绝对居中
Text(this.title + "")
.position({left:'50%'}).translate({x:'-50%'})
.lineHeight(25)
Row({space:5}){
this.buildMenuOneParam()
this.buildMenuTwoParam()
this.buildMenuThreeParam()
}
.height('100%').margin({right:15})
}
.width('100%')
.height(25)
.margin({top:10})
}
}
调用使用:
import {NavigationBar} from '../ets/common/components/NavigationBar'
//全局的自定义函数
@Builder function buildBackButton(){
Button({ type: ButtonType.Normal, stateEffect: false }) {
Image($r('app.media.down'))
}
.width(25).height(25).borderRadius(50)
.backgroundColor('rgba(255,255,255,0)')
}
@Entry
@Component
struct Parent {
//图片资源换成自己的就好,放入resource/base/media下就行
@Builder buildOneMenu(){
Button({ type: ButtonType.Normal, stateEffect: false }) {
Image($r('app.media.more_one'))
}
.width(25).height(25).borderRadius(50)
.backgroundColor('rgba(255,255,255,0)')
}
@Builder buildTwoMenu(){
Button({ type: ButtonType.Normal, stateEffect: false }) {
Image($r('app.media.search'))
}
.width(25).height(25).borderRadius(50)
.backgroundColor('rgba(255,255,255,0)')
}
@Builder buildThreeMenu(){
Button({ type: ButtonType.Normal, stateEffect: false }) {
Image($r('app.media.preview_open'))
}
.width(25).height(25).borderRadius(50)
.backgroundColor('rgba(255,255,255,0)')
}
build() {
Column() {
NavigationBar({title:"标题一"
,buildButtonBackParam:buildBackButton
,buildMenuOneParam:():void=>{this.buildOneMenu()}//this的指向是当前父页面
,buildMenuTwoParam:this.buildTwoMenu
})
NavigationBar({title:"标题二"
,buildButtonBackParam:buildBackButton
,buildMenuOneParam:():void=>{this.buildOneMenu()}
,buildMenuTwoParam:this.buildTwoMenu
,buildMenuThreeParam:this.buildThreeMenu
})
}
}
}