自定义组件之<七>自定义组件之插槽(slot)

2024-12-31 10:13:13
31次阅读
0个评论
最后修改时间:2024-12-31 10:13:50

9.7:自定义组件之插槽

笔者在前 5 节讲述的自定义组件的实现和使用中有一种情形并没有介绍,就是开发者在使用我们提供的自定义组件的时候如果想往自定义组件内添加一些额外的子组件,在不修改我们组件源码的情况下该如何实现喃?对于这种场景,ArkUI开发框架提供了 @BuilderParam 修饰符来解决这种问题,本节笔者就简单介绍一下 @BuilderParam 修饰符的使用。

9.7.1:@BuilderParam属性发现

笔者在学习自定义组件的时候,突发奇想,如果自定义组件返回的是一个容器布局结构,那么直接给自定义组件添加一个子组件是不是可行?于是笔者做了如下实验,首先定义了一个组件 CustomWidget ,代码如下:

@ComponentV2 struct CustomWidget {
  build() {
    Column() {
    }
    .width("100%")
    .height(100)
    .backgroundColor("#aabbcc")
  }
}

自定义的组件 CustomWidget 返回一个带有背景色的 Column ,因为它返回的是一个容器组件,笔者就想当然的认为可以像使用其它容器组件一样直接给 CustomWidget 组件添加子组件,于是就尝试了一下,代码写法如下所示:

@Entry @Component struct CustomWidgetTest {
  build() {
    Column() {
      CustomWidget() {   // 使用CustomWidget组件并给它添加了一个子组件Text
        Text('测试子组件') // 添加子组件后编译报错
      }
    }
    .width('100%')
    .height('100%')
  }
}

笔者打开 Previewer 准备看下运行效果,结果编译报错,报错信息如下所示:

[Compile Result]  ETS:ERROR File: ***/entry/src/main/ets/MainAbility/pages/index.ets:4:7
[Compile Result]  In the trailing lambda case, 'CustomWidget' must have one and only one property decorated with @BuilderParam, and its @BuilderParam expects no parameter.

根据报错信息提示,组件 CustomWidget 必须有且只有一个 @BuilderParam 修饰的属性且该属性不需要参数。这就是笔者发现 @BuilderParam 修饰符的由来。

9.7.2:@BuilderParam属性定义

declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;

/**
 * Defining BuilderParam PropertyDecorator
 * @since 7
 */
declare const BuilderParam: PropertyDecorator;

BuilderParam 定义在 common.d.ts 文件中,它是一个属性修饰符,修饰的属性类型为 () => {} ,因此需要在自定义组件 CustomWidget 内部声明一个属性,比如 child,代码如下所示:

@Component struct CustomWidget {

  @BuilderParam child: () => {}; // 声明属性child,该属性返回一个对象。

  // 省略部分代码
}

9.7.3:@BuilderParam使用介绍

CustomWidget 组件添加 child 属性后,表示该组件具备了额外添加子组件的能力,接下来在需要添加子组件的地方使用 child 属性做占位即可,代码如下所示:

@ComponentV2 struct CustomWidget {

  @BuilderParam child: () => {}  // 声明子组件占位符child

  build() {
    Column() {
      Text('原始子组件1')
        .fontSize(20)
      this.child()               // 在这里插入额外的子组件
      Text('原始子组件2')
        .fontSize(20)
      this.child()               // 在这里插入额外的子组件
    }
    .width('100%')
    .backgroundColor("#aabbcc")
  }
}

CustomWidget 组件添加完占位后,就可以直接给其添加子组件了,代码如下所示:

@Entry @ComponentV2 struct CustomWidgetTest {
  build() {
    Column() {
      CustomWidget() {      // 使用CustomWidget组件并给它添加了两个子组件Text
        Text('添加子组件aaa') // 添加子组件
          .fontSize(20)
          .backgroundColor(Color.Pink)
        Text('添加子组件bbb') // 添加子组件
          .fontSize(20)
          .backgroundColor(Color.Pink)
      }
    }
    .width('100%')
    .height('100%')
  }
}

还可以使用 @Builder 的方式添加子组件,如下所示:

@Entry @ComponentV2 struct CustomWidgetTest {

  @Builder customBuilder() {
    Column() {
      Text('添加子组件aaa') // 添加子组件
        .fontSize(20)
        .backgroundColor(Color.Pink)
      Text('添加子组件bbb') // 添加子组件
        .fontSize(20)
        .backgroundColor(Color.Pink)
    }
  }

  build() {
    Column() {
      CustomWidget({
        child: this.customBuilder
      })
    }
    .width('100%')
    .height('100%')
  }
}

运行结果如下图所示:

9_7_3_1.png

9.7.4:小结

以上就是本节所讲述的利用 @BuilderParam 实现插槽的做法,它为自定义组件提供了额外添加子组件的能力,读者可以合理使用该属性实现强大且灵活的自定义组件。

备注

作者:灰太狼

出处:https://www.arkui.club/

链接:https://www.nutpi.net/

來源:坚果派

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。否则追究相关责任。

收藏00

登录 后评论。没有帐号? 注册 一个。