在复杂组件开发中,经常需要让使用者在不修改源码的前提下,向自定义组件内部注入额外的内容。ArkUI 提供了 @BuilderParam 属性装饰器来实现这一“插槽”能力,本文将演示如何为组件动态添加子组件。

插槽需求与问题

假设我们定义了一个名为 CustomWidget 的简单容器组件,返回一个带背景色的 Column

@Component struct CustomWidget {
  build() {
    Column() {
      // 默认内容
    }
    .width("100%")
    .height(100)
    .backgroundColor("#aabbcc")
  }
}

如果在使用时这样写:

CustomWidget() {
  Text("我是插入的子组件")
}

编译会报错:

In the trailing lambda case, 'CustomWidget' must have one and only one property decorated with @BuilderParam ...

说明组件必须显式声明一个可接收插入内容的属性。

@BuilderParam 定义与用法

  1. 在组件内部声明插槽属性
    使用 @BuilderParam 修饰一个属性,类型为无参数函数,返回 void 或者一个根布局节点:

    @Component struct CustomWidget {
      @BuilderParam child: () => {};
    
      build() {
        Column() {
          Text("原始子组件1")
          this.child()      // 插槽1
          Text("原始子组件2")
          this.child()      // 插槽2
        }
        .width("100%")
        .backgroundColor("#aabbcc")
      }
    }
    
  2. 在使用处传递子组件
    因为声明了 @BuilderParam child,就可以像标准容器那样,用大括号传入任意多个子节点:

    @Entry @Component struct CustomWidgetTest {
      build() {
        Column() {
          CustomWidget() {
            Text("插槽内容 A").fontSize(20).backgroundColor(Color.Pink)
            Text("插槽内容 B").fontSize(20).backgroundColor(Color.Pink)
          }
        }
        .width("100%")
        .height("100%")
      }
    }
    

    渲染时,框架会多次调用 this.child(),依次插入所有传入的子组件。

插槽优势与扩展

  • 多处插入:同一个插槽可在组件内多次渲染,极大灵活性。
  • 可选内容:未传递插槽时 this.child 会是空函数,无需额外判断。
  • 组合复用:可将不同布局抽象为通用容器,使用插槽在具体场景中复用。

借助 @BuilderParam,你可以轻松为自定义组件开放“挂件”能力,而无需为每一种内容变种写模板,极大提高可维护性和扩展性。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐