Bootstrap

【HarmonyOS 4.0】@BuilderParam 装饰器

1. @BuilderParam 装饰器

  1. @BuilderParam 装饰器用于装饰自定义组件(struct)中的属性,其装饰的属性可作为一个UI结构的占位符,待创建该组件时,可通过参数为其传入具体的内容。
  2. 参数必须满足俩个条件:
    2.1 参数类型必须是个函数;
    2.2 参数必须是个UI结构;
  3. 因此这个参数就是 @Builder 方法
  4. 在这里插入图片描述

1.1 代码案例如下:

// 第一个Builder
@Builder
export function imageBuilder() {
  Column({ space: 10 }) {
    Image($r('app.media.app_icon'))
      .width('70%')
      .height('70%')
      .objectFit(ImageFit.Contain)
    Text('@BuilderParam装饰器:引用@Builder函数')
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
  }
}

// 第二个Builder
@Builder
export function textBuilder() {
  Column({ space: 10 }) {
    Text('@BuilderParam装饰器:引用@Builder函数')
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
    Text('当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。')
      .fontSize(14)
      .textOverflow({ overflow: TextOverflow.Ellipsis })
      .maxLines(6)
  }
}

// 自定义子组件
import { textBuilder } from './TextBuilder'

@Extend(Column)
function columnStyle() {
  .width('90%')
  .height(180)
  .borderRadius(10)
  .shadow({ radius: 20 })
  .padding(10)
}

@Component
export struct Card {
  @BuilderParam content: () => void = textBuilder

  build() {
    Column({ space: 20 }) {
      Column() {
        this.content()
      }
      .columnStyle()
    }
  }
}

// 父组件
import { imageBuilder } from "./ImageBuilder"
import { textBuilder } from './TextBuilder'
import { Card } from "./Card"

@Entry
@Component
struct Index {
  private scroller: Scroller = new Scroller()

  build() {
    Scroll(this.scroller) {
      Column({ space: 20 }) {
        Card({ content: imageBuilder })
        Card({ content: textBuilder })
        Divider()
        Card({ content: textBuilder })
        Card({ content: imageBuilder })
      }
      .width('100%')
    }
  }
}

1.2 如果一个组件只定义一个 @BuilderParam 属性,那么创建该组件时,也可直接通过“子组件”的方式传入具体的UI结构。

// 子组件
@Extend(Column)
function columnStyle() {
  .width('90%')
  .height(180)
  .borderRadius(10)
  .shadow({ radius: 20 })
  .padding(10)
}

@Component
export struct Card {
  @BuilderParam content: () => void

  build() {
    Column({ space: 20 }) {
      Column() {
        this.content()
      }
      .columnStyle()
    }
  }
}

// 父组件
import { Card } from "./Card"

@Entry
@Component
struct Index {
  build() {
    Column({ space: 20 }) {
      Card() {
        Column({ space: 10 }) {
          Image($r('app.media.app_icon'))
            .width('70%')
            .height('70%')
            .objectFit(ImageFit.Contain)
          Text('@BuilderParam装饰器:引用@Builder函数')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
        }
      }
    }
    .height('100%')
    .width('100%')
  }
}

1.3 未知代码:

// 第一个Builder
@Builder
export function imageBuilder(title: string) {
  Column({ space: 10 }) {
    Image($r('app.media.app_icon'))
      .width('70%')
      .height('70%')
      .objectFit(ImageFit.Contain)
    Text(title)
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
  }
}

// 第二个Builder
class TextObjBuilder {
  title: string = ''
  container: string = ''
}

@Builder
export function textBuilder($$: TextObjBuilder) {
  Column({ space: 10 }) {
    Text($$.title)
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
    Text($$.container)
      .fontSize(14)
      .textOverflow({ overflow: TextOverflow.Ellipsis })
      .maxLines(6)
  }
}

// 自定义组件
import { imageBuilder } from "./ImageBuilder"
import { textBuilder } from './TextBuilder'

@Extend(Column)
function columnStyle() {
  .width('90%')
  .height(180)
  .borderRadius(10)
  .shadow({ radius: 20 })
  .padding(10)
}

class TextObjBuilder {
  title: string = ''
  container: string = ''
}

@Entry
@Component
struct Index {
  @State title: string = '@BuilderParam装饰器:引用@Builder函数'
  @State container: string =
    '当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。'
  @BuilderParam content1: (title: string) => void = imageBuilder
  @BuilderParam content2: (TextObjBuilder: TextObjBuilder) => void = textBuilder

  build() {
    Column({ space: 20 }) {
      Column() {
        this.content1(this.title)
      }
      .columnStyle()

      Column() {
        this.content2({ title: this.title, container: this.container })
      }
      .columnStyle()
    }
    .height('100%')
    .width('100%')
  }
}
;