HarmonyOS开始玩耍:@Builder装饰器,自定义构建函数(十二)

243 阅读2分钟

一、自定义构建函数

ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。

1、自定义组件内自定义构建函数

定义的语法:

@Builder MyBuilderFunction(){}

1

使用方法:

this.MyBuilderFunction()

1
  • 允许在自定义组件内定义一个或多个@Builder方法,该方法被认为是该组件的私有、特殊类型的成员函数。
  • 自定义构建函数可以在所属组件的build方法和其他自定义构建函数中调用,但不允许在组件外调用。
  • 在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。
2、全局自定义构建函数

定义的语法:

@Builder function MyGlobalBuilderFunction(){}

1

使用方法:

MyGlobalBuilderFunction()

1
  • 全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。
  • 如果不涉及组件状态变化,建议使用全局的自定义构建方法。
3、参数传递规则

自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:

  • 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
  • 在自定义构建函数内部,不允许改变参数值。如果需要改变参数值,且同步回调用点,建议使用@Link。
  • @Builder内UI语法遵循UI语法规则。
  • 只有传入一个参数,且参数需要直接传入对象字面量才会按引用传递该参数,其余传递方式均为按值传递。

按值传递参数

@Builder function overBuilder(paramA1: string) {
  Row() {
    Text(`UseStateVarByValue: ${paramA1} `)
  }
}
@Entry
@Component
struct Parent {
  @State label: string = 'Hello';
  build() {
    Column() {
      overBuilder(this.label)
    }
  }
}


二、示例演示

List组件实现图文文章列表布局以及自定义模型类的使用

1、Image组件

Image为图片组件,常用于在应用中显示图片。Image支持加载string、PixelMap和Resource类型的数据源,支持png、jpg、bmp、svg和gif类型的图片格式。

Image(src: string | PixelMap | Resource)


Image组件加载图片失败或图片尺寸为0时,图片组件大小自动为0,不跟随父组件的布局约束。

属性:

名称参数类型描述
objectFitImageFit设置图片的填充效果。 默认值:ImageFit.Cover
altstring、Resource加载时显示的占位图,支持本地图片(png、jpg、bmp、svg和gif类型),不支持网络图片。 默认值:null

ImageFit:

名称描述
Contain保持宽高比进行缩小或者放大,使得图片完全显示在显示边界内。
Cover保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
Auto自适应显示
Fill不保持宽高比进行放大缩小,使得图片充满显示边界。
ScaleDown保持宽高比显示,图片缩小或者保持不变。
None保持原有尺寸显示。
2、layoutWeight属性
名称参数说明描述
layoutWeightnumber、string父容器尺寸确定时,设置了layoutWeight属性的子元素与兄弟元素占主轴尺寸按照权重进行分配,忽略元素本身尺寸设置,表示自适应占满剩余空间。 默认值:0 从API version 9开始,该接口支持在ArkTS卡片中使用。 说明: 仅在Row/Column/Flex布局中生效。 可选值为大于等于0的数字,或者可以转换为数字的字符串。
3、定义模型类

在 ArkTS 中定义模型类与在纯 TypeScript 项目中定义类没有本质区别。但是,在 UI 开发中,你可能不会直接在组件的模板中使用模型类的实例。相反,你可能会将这些实例绑定到组件的响应式状态变量上,并在模板中使用这些状态变量。这样做的好处是,当状态变量发生变化时,UI 可以自动更新。

4、代码
// 定义模型类
class Item {
  id: number;
  title: string;
  img: ResourceStr;
  author: string;
  date: string;

  constructor(id: number, title: string, img: ResourceStr, author: string, date: string) {
    this.id = id
    this.title = title
    this.img = img
    this.author = author
    this.date = date
  }
}

// 全局自定义构建函数
@Builder function newsItem(item:Item){
  Row() {
    Column() {
      Text(item.title)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .maxLines(2)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
      Text(`${item.author} ${item.date}`)
        .fontSize(14)
    }
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Start)
    .height(68)
    .justifyContent(FlexAlign.SpaceBetween)

    Image(item.img)
      .width(100)
      .height(68)
      .margin({ left: 8 })
      .borderRadius(2)
      .objectFit(ImageFit.Cover)
  }
  .width('100%')
  .height(80)
}

@Entry
@Component
struct NewsBuilder {
  @State articleList: Item[] = [
    new Item(1, "嫦娥六号探测器进入环月轨道飞行", "https://p5.img.cctvpic.com/photoworkspace/contentimg/2024/05/08/2024050820144382684.jpg", "央视网", "2014-05-08"),
    new Item(2, "“五一”假期游处处火爆 有哪些文旅新潮流?", "https://cms-emer-res.cctvnews.cctv.com/image/1005/upload/17292d188bc64cef882f1cd07d3d2acc.jpeg", "央视新闻客户端", "2024-05-08"),
    new Item(3, "杭州:全面取消住房限购,购房即可申请落户", $r("app.media.2"), "界面新闻", "2024-05-09"),
    new Item(4, "时隔五年,合肥或将再次引进“国宝”大熊猫", "https://pics4.baidu.com/feed/d50735fae6cd7b899b1d7bef7ec7b8aad8330e5d.jpeg@f_auto?token=e70fa976dceb8e88433c493f7e86b88c", "九派新闻", "2024-05-08"),
    new Item(5, "发布擦边广告再被罚,椰树集团徘徊在“土味”和“低俗”之间?", "https://pics1.baidu.com/feed/e824b899a9014c083cd8d85d067bf9057af4f471.jpeg@f_auto?token=c6770b5d0d99a68721fc88e7a337d01c", "北京商报", "2024-05-08"),
    new Item(6, "特斯拉在华推进全自动驾驶 智能网联车产业链迎新机遇", $r("app.media.2"), "每日经济新闻", "2024-05-09"),
  ]

  build() {
    Column() {
      List() {
        ForEach(this.articleList, (item: Item) => {
          ListItem() {
            newsItem(item)
          }
          .padding({ top: 5, bottom: 5 })
        })
      }
      .divider({ strokeWidth: 1, color: "#eeeeee" })
      .backgroundColor(0xffffff)
      .borderRadius(10)
      .padding(10)
    }.padding(10)
    .backgroundColor(0xeeeeee)
    .width('100%')
    .height('100%')
  }
}


5、效果

在这里插入图片描述

我的博客只写前端博文,点击我去看更多喜欢的前端博文,欢迎大家一起讨论学习!【https://blog.csdn.net/qq_29101285?spm=1011.2266.3001.5343】