在 ArkTS 开发中,如果我们要实现类似 Vue 的
<slot>(插槽)功能,允许父组件向子组件内部注入自定义的 UI 结构,就需要用到@BuilderParam装饰器。
下面通过一个完整的示例,演示它的三种核心应用场景:
/**
* 子组件:定义插槽与默认兜底内容
*/
@Component
struct ChildComponent {
// 1. 定义插槽(要求传入一个带 string 参数的 UI 构建函数)
// '= this.defaultBuilder' 表示如果外部不传,就用默认的
@BuilderParam content: (label: string) => void = this.defaultBuilder;
// 2. 默认的 UI 构建逻辑(兜底显示)
@Builder
defaultBuilder(label: string) {
Text(`${label}:这是子组件自带的默认内容`)
.fontColor(Color.Gray)
.fontSize(16)
}
build() {
Column() {
// 3. 在 UI 结构中渲染插槽,并向外抛出一个参数 "来自子组件的数据"
this.content("来自子组件的数据")
}
.width('90%')
.padding(20)
.backgroundColor('#F5F5F5')
.borderRadius(12)
}
}
/**
* 父组件:使用子组件,并演示三种插槽注入方式
*/
@Entry
@Component
struct BuilderParamDemoPage {
// 父组件准备好的自定义 UI 结构
@Builder
customContent(label: string) {
Text(`${label} => 这是父组件定制的专属 UI!`)
.fontColor(Color.Blue)
.fontSize(18)
.fontWeight(FontWeight.Bold)
}
build() {
Column({ space: 20 }) {
// 【场景一】不传参:直接显示子组件的默认内容
ChildComponent()
// 【场景二】覆盖 UI(闭包无参):忽略子组件传出的数据,完全由父组件自己硬编码
ChildComponent({
content: () => {
this.customContent("父组件硬编码标签")
}
})
// 【场景三】作用域插槽(接收参数):父组件的 UI 接收并使用了子组件传出的内部数据
ChildComponent({
content: (childLabel: string) => {
// 这里的 childLabel 就是子组件传出来的 "来自子组件的数据"
this.customContent(childLabel)
}
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#FFFFFF')
}
}代码原理解析:
@Builder:用于定义一段可复用的 UI 结构。@BuilderParam:相当于一个“占位符”,声明这个位置的 UI 结构由外部传入。参数传递:
this.content("...")执行时,子组件将参数传给了父组件,父组件的箭头函数(childLabel: string) => {}负责接收参数,并传递给自己的@Builder进行最终的渲染。