鸿蒙Harmony Os中的@Builder / @BuilderParam
一. @Builder装饰器:自定义构建函数
-
作用: 可以将重复使用的UI元素抽象成一个方法,并在 build 方法中进行调用。
-
使用范围: 组件内部或全局范围进行定义和使用。
-
组件内定义
less@Builder MyBuilderFun() {} 使用: this.MyBuilderFun()
-
全局范围定义
less@Builder function MyBuilderFun() {} 使用: MyGlobalBuilderFun()
-
-
demo,使用@Builder提取结构
- 全局声明需要加function关键字,使用时直接写函数名称。
scss@Entry @Component struct Demo { build() { Column({space:10}) { ListModel() }.width('100%') .height('100%') } } @Builder function ListModel(){ Row(){ Text("音乐") .width("100%") .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) } .width("100%") .height(100) .backgroundColor(Color.Brown) }
- 组件内声明,使用时需要用this
scss@Entry @Component struct Demo { @Builder ListModel(){ Row(){ Text("音乐") .width("100%") .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) } .width("100%") .height(100) .backgroundColor(Color.Brown) } build() { Column({space:10}) { this.ListModel() }.width('100%') .height('100%') } }
-
支持传递参数,动态渲染ui
![图片转存失败,建议将图片保存下来直接上传](/Users/chengang/Library/Application Support/typora-user-images/image-20240304113431754.png)
-
值传递
scss@Entry @Component struct Demo { @Builder ListModel({ title: string }){ Row(){ Text(title) .width("100%") .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) } .width("100%") .height(100) .backgroundColor(Color.Brown) } build() { Column({space:10}) { this.ListModel("音乐") this.ListModel("美术") this.ListModel("舞蹈") }.width('100%') .height('100%') } }
-
引用数据类型的传递
![图片转存失败,建议将图片保存下来直接上传](/Users/chengang/Library/Application Support/typora-user-images/image-20240304113903374.png)
scss@Builder function ListModel(params:{title:string,count:number}){ Row(){ Text(`${params.title}`) .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) Text(`投票人数:${params.count}`) .fontColor(Color.White) } .width("100%") .height(100) .backgroundColor(Color.Brown) .justifyContent(FlexAlign.SpaceAround) } @Entry @Component struct Index { @State CountMusic:number=10 build() { Column({space:10}) { ListModel({title:"音乐",count:this.CountMusic}) ListModel({title:"美术",count:30}) ListModel({title:"舞蹈",count:12}) Button("增加音乐支持人数").onClick(()=>{ this.CountMusic++; }) }.width('100%') .height('100%') } }
-
-
总结:
- 在使用 @Builder 复用逻辑时,可以支持传递参数,从而实现更灵活的UI渲染。
- 参数可以是状态数据,但建议使用对象的方式进行传递(直接传递,无法实现视图更新)。
- 可以使用 Component 来抽象组件,而 @Builder 则可以实现轻量级的UI复用。
二. @BuilderParam:是一个装饰器,用于声明任意UI描述的一个元素,类似于vue里的 slot 占位符。
-
作用: "插槽"类似,注意(@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。)
-
使用场景
-
尾随闭包初始化组件demo(默认插槽)
标题通过文字属性传入,内容通过"尾随闭包传入"
scss// ● 标题文字通过属性传入 // ● 内容结构"尾随闭包"传入 @Entry @Component struct Index { build() { Column({ space: 10 }) { ListModel({title:"音乐"}){ Text("音乐的内容") } ListModel({title:"美术"}){ Text("美术的内容") } ListModel({title:"舞蹈"}) }.width('100%').height('100%') } } @Component struct ListModel { title: string // ListContent 名字随便起,默认接收一个自定义构建函数 @BuilderParam ListContent: () => void = this.defaultContent; @Builder defaultContent () { Text('默认展示的内容') } build() { Column() { Text(this.title) .width('100%') .height(50) .textAlign(TextAlign.Center) this.ListContent(); }.width('100%').height(200).backgroundColor(Color.Brown) } }
-
参数初始化组件demo(具名插槽)
需要传入头部结构和底部结构
scss// 需求:需要传入头部结构和底部结构 @Entry @Component struct Index { @Builder ListHeaderContent () { Text("头部内容") .fontColor(Color.White) .height(40) .backgroundColor(Color.Blue) .width("100%") .textAlign(TextAlign.Center) } @Builder ListEndContent () { Text("尾部内容") .fontColor(Color.White) .height(40) .backgroundColor(Color.Blue) .width("100%") .textAlign(TextAlign.Center) } build() { Column() { ListModel({ title: '音乐', ListHeader: this.ListHeaderContent, ListEnd: () => {this.ListEndContent()} // 箭头函数 }) }.width('100%').height('100%') } } @Component struct ListModel { title: string @BuilderParam ListHeader: () => void = this.defaultHeader; @BuilderParam ListEnd: () => void = this.defaultEnd; @Builder defaultHeader() { Text('默认 header') } @Builder defaultEnd() { Text('默认 End') } build() { Column() { this.ListHeader(); Text(this.title) .width("100%") .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) this.ListEnd(); }.width('100%').height(200).backgroundColor(Color.Brown) } }
这不就是类似于vue的具名插槽吗???提取一个公共组件,引入,定制头和尾!!!
-
-
总结
- 当子组件使用一个 @BuilderParam 时,使用组件时可以在尾随的大括号 {} 中插入UI结构。
- 当子组件使用多个 @BuilderParam 时,可以在使用组件时传入参数,例如 Comp({ xxx: this.builderFn })。
- 不能既传递默认插槽也传递具名插槽,会报错。
- 子组件本身可以提供一个默认的 @Builder 函数,作为 @BuilderParam 的备用函数,用于作为备用内容。