#跟着若城学鸿蒙# 自定义组件之插槽
·
在实际开发中,我们经常会遇到这样的需求:当使用一个封装好的自定义组件时,希望在其内部自由插入任意子组件,以增强其灵活性和复用性。为了在不改动组件源码的前提下支持“向内部插槽插入子组件”,ArkUI 提供了 @BuilderParam 属性修饰符。下面从实战出发,完整介绍如何为自定义组件添加插槽能力。
1. 问题背景:直接嵌套失败
假设我们有这样一个最简单的自定义组件 CustomWidget,仅返回一个带背景色的 Column 容器:
@Component
struct CustomWidget {
build() {
Column() {
// 原始内部结构
}
.width("100%")
.height(100)
.backgroundColor("#aabbcc")
}
}
如果像使用普通容器那样,直接给它添加子组件:
@Entry @Component
struct CustomWidgetTest {
build() {
Column() {
CustomWidget() {
Text("测试子组件")
}
}
.width("100%")
.height("100%")
}
}
编译时就会报错:
ETS:ERROR … In the trailing lambda case, 'CustomWidget' must have one and only one
property decorated with @BuilderParam, and its @BuilderParam expects no parameter.
这说明:若想让 CustomWidget 接受嵌套构造子组件,必须在其内部显式声明一个标记为 @BuilderParam 的属性。
2. @BuilderParam 修饰符简介
在 common.d.ts 中,@BuilderParam 定义如下:
/**
* Defining BuilderParam PropertyDecorator
* @since 7
*/
declare const BuilderParam: PropertyDecorator;
- 作用:将组件的某个属性标记为“插槽”占位,该属性的类型必须为一个无参返回
JSX.Element(或组件容器)的函数签名:() => {}。 - 约束:每个组件只能有且只有一个
@BuilderParam属性,且不能带参数。
3. 在组件内部声明插槽
修改 CustomWidget,新增一个 @BuilderParam child 属性,并在 build() 方法中多次调用它来渲染插入内容:
@Component
struct CustomWidget {
@BuilderParam
child: () => {}; // 插槽属性,占位用
build() {
Column() {
Text("原始子组件 1")
.fontSize(20)
this.child() // 在此渲染外部插入的子组件
Text("原始子组件 2")
.fontSize(20)
this.child() // 同一插槽可重复调用
}
.width("100%")
.height(100)
.backgroundColor("#aabbcc")
}
}
这样,CustomWidget 就在两处预留了“插槽”位置,外部传入的子组件会在这两处同时渲染。
4. 在使用端插入子组件
在父组件中,就可以像使用系统容器那样,将任意组件写在 CustomWidget() 后的花括号里:
@Entry @Component
struct CustomWidgetTest {
build() {
Column() {
CustomWidget() {
Text("插入子组件 AAA")
.fontSize(18)
.backgroundColor(Color.Pink)
Text("插入子组件 BBB")
.fontSize(18)
.backgroundColor(Color.PeachPuff)
}
}
.width("100%")
.height("100%")
}
}
运行效果:
CustomWidget在其两处this.child()位置,都会同时渲染 “AAA” 与 “BBB” 两个Text。- 如果只想渲染一次插入内容,也可以在组件内部只调用一次
this.child()。
5. 小结
- 当自定义组件需要开放“容器式插槽”以供外部灵活注入子组件时,务必在组件内部声明一个带有
@BuilderParam的属性,并在build()中调用它; - 使用端只需在组件构造后紧跟花括号,像普通容器一样编写子节点即可;
- 这种插槽机制无需修改组件外的 API,只需在组件内部做最小范围的改动,大大提升了自定义组件的复用性与扩展性。
更多推荐




所有评论(0)