HarmonyOS鸿蒙Next中,@Builder装饰器如何创建可复用UI片段?@BuilderParam如何实现插槽?
HarmonyOS鸿蒙Next中,@Builder装饰器如何创建可复用UI片段?@BuilderParam如何实现插槽? 我想在 HarmonyOS 组件中复用 UI 代码片段,想了解:
-
@Builder 装饰器的作用是什么?与普通方法有什么区别?
-
如何向 @Builder 方法传递参数?
-
@BuilderParam 如何实现类似 Vue 插槽(Slot)的功能?
-
如何将 @Builder 作为参数传递给子组件?
希望能获取 @Builder 的完整使用示例。
更多关于HarmonyOS鸿蒙Next中,@Builder装饰器如何创建可复用UI片段?@BuilderParam如何实现插槽?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
实现思路:
- 使用 @Builder 装饰器定义可复用的 UI 片段,可以接收参数:
[@Builder](/user/Builder)
TabItem(title: string, index: number) {
Column() {
Text(title)
.fontSize(14)
.fontColor(this.selectedIndex === index ? '#007AFF' : '#666')
if (this.selectedIndex === index) {
Divider().width(20).strokeWidth(2).color('#007AFF')
}
}
.onClick(() => this.selectedIndex = index)
}
- 使用 @BuilderParam 定义插槽,允许父组件传入自定义内容:
@Component
struct SlotCard {
@Prop title: string = '';
[@BuilderParam](/user/BuilderParam) content: () => void = this.defaultContent;
[@Builder](/user/Builder) defaultContent() {
Text('默认内容')
}
build() {
Column({ space: 12 }) {
Text(this.title).fontSize(18).fontWeight(FontWeight.Bold)
this.content() // 渲染插槽内容
}
.padding(16)
.backgroundColor('#FFF')
.borderRadius(12)
}
}
- 父组件使用插槽传入自定义内容:
SlotCard({ title: '自定义卡片' }) {
Column({ space: 8 }) {
Text('自定义内容第一行')
Text('自定义内容第二行')
Button('操作按钮')
}
}
- 完整示例代码:
@Entry
@Component
struct BuilderExample {
@State selectedIndex: number = 0;
private tabs: string[] = ['首页', '分类', '我的'];
// 组件内 [@Builder](/user/Builder)
[@Builder](/user/Builder)
TabItem(title: string, index: number) {
Column() {
Text(title)
.fontSize(14)
.fontColor(this.selectedIndex === index ? '#007AFF' : '#666')
if (this.selectedIndex === index) {
Divider()
.width(20)
.strokeWidth(2)
.color('#007AFF')
.margin({ top: 4 })
}
}
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.onClick(() => this.selectedIndex = index)
}
[@Builder](/user/Builder)
customCardContent() {
Column({ space: 8 }) {
Text('这是自定义的卡片内容')
Image($r('app.media.photo')).width('100%').height(100).borderRadius(8)
Row({ space: 12 }) {
Button('取消').backgroundColor('#F0F0F0').fontColor('#333')
Button('确定').backgroundColor('#007AFF')
}
}
}
build() {
Column({ space: 16 }) {
// 使用 [@Builder](/user/Builder) 构建 Tab 栏
Row({ space: 24 }) {
ForEach(this.tabs, (tab: string, index: number) => {
this.TabItem(tab, index)
})
}
.width('100%')
.justifyContent(FlexAlign.Center)
.padding(12)
.backgroundColor('#FFF')
// 使用默认插槽
SlotCard({ title: '默认内容卡片' })
// 使用自定义插槽
SlotCard({ title: '自定义内容卡片' }) {
this.customCardContent()
}
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#F5F5F5')
}
}
@Component
struct SlotCard {
@Prop title: string = '';
[@BuilderParam](/user/BuilderParam) content: () => void = this.defaultContent;
[@Builder](/user/Builder) defaultContent() {
Text('这是默认内容').fontColor('#999')
}
build() {
Column({ space: 12 }) {
Text(this.title).fontSize(18).fontWeight(FontWeight.Bold)
this.content()
}
.width('100%')
.padding(16)
.backgroundColor('#FFF')
.borderRadius(12)
}
}
更多关于HarmonyOS鸿蒙Next中,@Builder装饰器如何创建可复用UI片段?@BuilderParam如何实现插槽?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
@Builder与@BuilderParam装饰器
@Builder装饰器
@Builder装饰器用于创建可复用的UI片段,通过函数方式定义组件,支持参数传递。
@BuilderParam装饰器
@BuilderParam用于声明UI插槽,接收@Builder方法或闭包作为参数,实现动态UI组合。
结合使用
两者结合可实现灵活的自定义组件构建。
1. @Builder装饰器的作用与区别
@Builder装饰器用于构建可复用的UI描述片段,本质上是一个UI构建函数。与普通方法的核心区别在于:
- 声明式UI:@Builder方法内使用声明式UI语法(如Column、Text),而普通方法通常处理逻辑或返回数据。
- this上下文:@Builder方法内
this指向所属组件实例,普通方法遵循标准函数作用域。 - 调用方式:@Builder方法通过花括号
{}调用(如this.MyBuilder()),普通方法直接调用。
2. 向@Builder传递参数
支持两种参数传递方式:
- 常规参数:直接传递基本类型或对象。
[@Builder](/user/Builder) function MyBuilder(param1: string, param2: number) { Text(param1).fontSize(param2) } // 调用 MyBuilder('Hello', 20) - TS方法引用:传递一个无返回值的函数类型参数。
[@Builder](/user/Builder) function MyBuilder(action: () => void) { Button('Click').onClick(action) }
3. 组件内@Builder vs 全局@Builder
- 组件内@Builder:定义在组件内,可访问组件状态(
this),通过this.BuilderName()调用。 - 全局@Builder:定义在组件外(如单独ts文件),无组件状态访问权限,通过函数名直接调用。
4. @BuilderParam实现插槽功能
@BuilderParam用于组件定义占位参数,接收@Builder类型参数实现动态UI插入:
// 子组件
@Component
struct ChildComponent {
[@BuilderParam](/user/BuilderParam) content: () => void
build() {
Column() {
this.content() // 插槽位置
}
}
}
// 父组件使用
@Entry
@Component
struct ParentComponent {
[@Builder](/user/Builder) customSlot() {
Text('插槽内容')
}
build() {
Column() {
ChildComponent({ content: this.customSlot }) // 传递Builder
}
}
}
5. 完整使用示例
// 全局Builder(无状态访问)
[@Builder](/user/Builder)
function GlobalBuilder(msg: string) {
Text(msg).fontColor(Color.Red)
}
// 组件定义
@Component
struct MyComponent {
[@State](/user/State) count: number = 0
// 组件内Builder(可访问this)
[@Builder](/user/Builder)
private InnerBuilder(label: string) {
Row() {
Text(`${label}: ${this.count}`).fontSize(18)
}
}
// 接收Builder参数
[@BuilderParam](/user/BuilderParam) dynamicUI?: () => void
build() {
Column() {
// 调用全局Builder
GlobalBuilder('全局内容')
// 调用组件内Builder
this.InnerBuilder('计数')
// 渲染动态插槽
if (this.dynamicUI) {
this.dynamicUI()
}
Button('增加').onClick(() => { this.count++ })
}
}
}
// 使用组件并传递Builder
@Entry
@Component
struct ParentComponent {
[@Builder](/user/Builder) customBuilder() {
Column() {
Text('自定义插槽').fontWeight(FontWeight.Bold)
Divider().strokeWidth(2)
}
}
build() {
Column() {
MyComponent({ dynamicUI: this.customBuilder })
}
}
}
关键点总结:
- @BuilderParam必须与@Builder配合使用,实现UI片段参数化
- 组件内Builder可响应状态变化(如@State)
- 通过TS函数类型约束Builder参数格式
- 插槽内容在子组件中通过
this.builderParamName()渲染

