ArkTS 实现自定义组件插槽

180 阅读2分钟

在HarmonyOS中,如何实现类似Vue-Slot或React-RenderProps的功能?即允许将UI结构的函数(被@Builder修饰的函数)作为参数传递给组件,并在组件内的指定位置渲染,可以使用@BuilderParam装饰器。

@BuilderParam

当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量(@BuilderParam是用来承接@Builder函数的)。

开发者可以在初始化自定义组件时,使用不同的方式(如:参数修改、尾随闭包、借用箭头函数等)对@BuilderParam装饰的自定义构建函数进行传参赋值,在自定义组件内部通过调用@BuilderParam为组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

具体实例

image.png

想要实现一个 Demo 组件,开发者传入 title,以及一个插槽的具体实现

使用步骤

  1. 子组件声明 @BuilderParam 属性。
  2. 父组件传入 @Builder修饰的函数或箭头函数。
  3. 调用 @Builder函数的逻辑。

BuilderParam的参数可以不给初始值,如果给了初始值, 就是没有内容的默认内容

具体代码

@Component
struct Demo {
  @Prop title: string

  @Builder
  slotBuilder() {
  };

  @BuilderParam slotBuilderParam: () => void = this.slotBuilder;

  build() {
    Column() {
      Text(this.title).padding(10).backgroundColor('#f1f3f5').width('100%')
      Column() {
        this.slotBuilderParam()

      }.width('100%').backgroundColor('#fff')
    }

  }
}


export default Demo

外部调用

import Demo from '../components/Demo';

@Entry
@Component
struct StateAndProp {
  scroller: Scroller = new Scroller()
  @State count: number = 0;
 

  @Builder
  normalBuilder() {
    Column() {
      Row() {
        Text(this.count.toString())
        Button('点击').onClick(() => this.count++)
      }
      Sub0({ count: this.count })
      Sub1({ count: this.count })
    }
  }

  build() {
    Flex({
      direction: FlexDirection.Column,
      justifyContent: FlexAlign.Start
    }) {
      NavBack()

      Scroll(this.scroller) {
        Column() {
          Demo({
            title: '非嵌套类型',
            slotBuilderParam: (): void => {
              this.normalBuilder()
            }
          })

          
        }
      }
    }
  }
}