在HarmonyOS中,如何实现类似Vue-Slot或React-RenderProps的功能?即允许将UI结构的函数(被@Builder修饰的函数)作为参数传递给组件,并在组件内的指定位置渲染,可以使用@BuilderParam装饰器。
@BuilderParam
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量(@BuilderParam是用来承接@Builder函数的)。
开发者可以在初始化自定义组件时,使用不同的方式(如:参数修改、尾随闭包、借用箭头函数等)对@BuilderParam装饰的自定义构建函数进行传参赋值,在自定义组件内部通过调用@BuilderParam为组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
具体实例
想要实现一个 Demo 组件,开发者传入 title,以及一个插槽的具体实现
使用步骤
- 子组件声明
@BuilderParam属性。 - 父组件传入
@Builder修饰的函数或箭头函数。 - 调用
@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()
}
})
}
}
}
}
}