wrapBuilder:封装全局@Builder
@Builder 构建的构造函数无法作为参数传递,ArkUI 引入了wrapBuilder作为全局@Builder 的封装函数,wrapBuilder 会返回一个WrappedBuilder对象,用于全局@Builder 的赋值和传递。
- wrapBuilder 方法只能传入全局@Builder方法
- 在同一个自定义组件内,同一个 wrapBuilder 只能初始化一次,再次调用将不会生效
- WrappedBuilder 对象的 builder 属性方法仅限在
struct内部使用
wrapBuilder
wrapBuilder是一个模板函数,返回一个 WrappedBuilder 对象
declarefunctionwrapBuilder<ArgsextendsObject[]>(builder:(...args:Args)=>void):WrappedBuilder<Args>;WrappedBuilder对象也是一个模板类
declareclassWrappedBuilder<ArgsextendsObject[]>{builder:(...args:Args)=>void;constructor(builder:(...args:Args)=>void);}模板参数
Args extends Object[]需要匹配 @Builder 函数参数的类型
【示例】
@BuilderfunctionitemBuilder(value:string,size:number){Text(value).fontSize(size)}//WrappedBuilder 的参数类型,与 @Builder 函数的参数类型一致letglobalBuilder:WrappedBuilder<[string,number]>=wrapBuilder(itemBuilder);@Componentstruct TestIndex{@Statemessage:string='wrapBuilder test'build(){Column(){globalBuilder.builder(this.message,50)}.width('100%').height('100%')}}【引用传递】
按引用传递参数时,状态变量的改变会引起 @Builder 方法内的UI刷新
classTemplateData{publicfloorName:string='test'}@BuilderfunctionfloorBuilder(data:TemplateData){Text(data.floorName).width('100%').textAlign(TextAlign.Center).borderWidth(1)}constfloorBuild:WrappedBuilder<[TemplateData]>=wrapBuilder(floorBuilder);@Entry@Componentstruct Index{@Statedata:TemplateData=newTemplateData();build(){Column({space:20}){// 按引用传入参数时,状态变量的改变会引起 @Builder 方法内的 UI 刷新floorBuild.builder({floorName:this.data.floorName})// 直接传入对象实例,状态变量的改变不会触发 UI 刷floorBuild.builder(this.data)Button('change name').onClick(()=>{this.data.floorName+='-'})}}}mutableBuilder
API22 开始,推荐使用mutableBuilder,支持二次赋值后刷新UI
wrapBuilder 只能初始化一次,不支持动态切换 @Builder,引入 mutableBuilder 作为动态全局 @Builder 的封装函数,mutableBuilder 返回 MutableBuilder 对象,用于全局 @Builder 的动态刷新。
mutableBuilder是一个模板函数,返回一个 MutableBuilder 对象
declarefunctionmutableBuilder<ArgsextendsObject[]>(builder:BuilderCallback):MutableBuilder<Args>;MutableBuilder对象是一个模板类,继承自 WrappedBuilder
declareclassMutableBuilder<ArgsextendsObject[]>extendsWrappedBuilder<Args>{}MutableBuilder 继承自 WrappedBuilder,即 mutableBuilder 对应的 @Builder 具有与 WrappedBuilder 同等能力,其也可用于创建 ComponentContent 实例,作为
openCustomDialog、tabBar等的入参
- mutableBuilder 方法只能传入全局@Builder方法,传入局部@Builder方法编译时报错
- MutableBuilder 对象的 builder 方法仅限在自定义组件内部使用,在自定义组件外面使用会导致程序运行时崩溃
- MutableBuilder 与 wrapBuilder 不可混用,会导致不符合预期的更新
动态更新全局@Builder
@BuilderfunctiontextBuilder(title:string){Text(title).width('100%').textAlign(TextAlign.Center).borderWidth(1)}@BuilderfunctionbuttonBuilder(title:string){Button(title)}@Entry@Componentstruct Index{@StatebuildText:boolean=true;@Statemessage:string='text builder';@LocalcontentBuild:MutableBuilder<[string]>=mutableBuilder(textBuilder);build(){Column({space:20}){this.contentBuild.builder(this.message)// 点击按钮,动态更新 @BuilderButton('change builder').onClick(()=>{this.buildText=!this.buildText;if(this.buildText){this.message='text builder';this.contentBuild=mutableBuilder(textBuilder);}else{this.message='button builder';this.contentBuild=mutableBuilder(buttonBuilder);}})}}}@Monitor 监听 @Builder 的变化
mutableBuilder对应的 @Builder 函数中可使用MutableBinding进行包裹来观察状态变量的变化,同时可通过@Monitor或addMonitor监听 mutableBuilder 中 @Builder 的变化
@BuilderfunctiontextBuilder(title:string){Text(title).width('100%').textAlign(TextAlign.Center).borderWidth(1)}@BuilderfunctionbuttonBuilder(title:string){Button(title)}@Entry@Componentstruct Index{@StatebuildText:boolean=true;@Statemessage:string='text builder';@LocalcontentBuild:MutableBuilder<[string]>=mutableBuilder(textBuilder);@Monitor('contentBuild')variableChange(m:IMonitor):void{console.info('Builder changed');}build(){Column({space:20}){this.contentBuild.builder(this.message)// 点击按钮,动态更新 @BuilderButton('change builder').onClick(()=>{this.buildText=!this.buildText;if(this.buildText){this.message='text builder';this.contentBuild=mutableBuilder(textBuilder);}else{this.message='button builder';this.contentBuild=mutableBuilder(buttonBuilder);}})}}}点击按钮,切换 @Builder 时,@Monitor 会监听到全局 @Builder 的变化,打印日志