@Builder装饰器:自定义构建函数

前面章节介绍了如何创建一个自定义组件。该自定义组件内部UI结构固定,仅与使用方进行数据传递。ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

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

说明

从API version 9开始,该装饰器支持在ArkTS卡片中使用。

装饰器使用说明

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

定义的语法:

@Builder MyBuilderFunction(){ ... }
  • 1.

使用方法:

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

定义的语法:

@Builder function MyGlobalBuilderFunction(){ ... }
  • 1.

使用方法:

MyGlobalBuilderFunction()
  • 1.
  • 全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。
  • 如果不涉及组件状态变化,建议使用全局的自定义构建方法。

参数传递规则

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

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

按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新。ArkUI提供$$作为按引用传递参数的范式。

ABuilder( $$ : { paramA1: string, paramB1 : string } );
@Builder function ABuilder($$: { paramA1: string }) {  Row() {    Text(`UseStateVarByReference: ${$$.paramA1} `)  }}@Entry@Componentstruct Parent {  @State label: string = 'Hello';  build() {    Column() {      // 在Parent组件中调用ABuilder的时候,将this.label引用传递给ABuilder      ABuilder({ paramA1: this.label })      Button('Click me').onClick(() => {        // 点击“Click me”后,UI从“Hello”刷新为“ArkUI”        this.label = 'ArkUI';      })    }  }}
  • 1.
  • 2.
按值传递参数

调用@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起@Builder方法内的UI刷新。所以当使用状态变量的时候,推荐使用 按引用传递

@Builder function ABuilder(paramA1: string) {  Row() {    Text(`UseStateVarByValue: ${paramA1} `)  }}@Entry@Componentstruct Parent {  label: string = 'Hello';  build() {    Column() {      ABuilder(this.label)    }  }}
  • 1.

@BuilderParam装饰器:引用@Builder函数

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

说明

从API version 9开始,该装饰器支持在ArkTS卡片中使用。

装饰器使用说明

初始化@BuilderParam装饰的方法

@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。

  • 使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化@BuilderParam。
@Builder function GlobalBuilder0() {}
@Componentstruct Child {  @Builder doNothingBuilder() {};
  @BuilderParam aBuilder0: () => void = this.doNothingBuilder;  @BuilderParam aBuilder1: () => void = GlobalBuilder0;  build(){}}
  • 1.
  • 2.
  • 3.
  • 用父组件自定义构建函数初始化子组件@BuilderParam装饰的方法。
@Componentstruct Child {  @BuilderParam aBuilder0: () => void;
  build() {    Column() {      this.aBuilder0()    }  }}
@Entry@Componentstruct Parent {  @Builder componentBuilder() {    Text(`Parent builder `)  }
  build() {    Column() {      Child({ aBuilder0: this.componentBuilder })    }  }}
  • 1.
  • 2.
  • 3.
  • 4.

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_harmonyos

  • 需注意this指向正确。
    以下示例中,Parent组件在调用this.componentBuilder()时,this指向其所属组件,即“Parent”。@Builder componentBuilder()传给子组件@BuilderParam aBuilder0,在Child组件中调用this.aBuilder0()时,this指向在Child的label,即“Child”。
    说明
    开发者谨慎使用bind改变函数调用的上下文,可能会使this指向混乱。
@Componentstruct Child {  label: string = `Child`  @BuilderParam aBuilder0: () => void;
  build() {    Column() {      this.aBuilder0()    }  }}
@Entry@Componentstruct Parent {  label: string = `Parent`
  @Builder componentBuilder() {    Text(`${this.label}`)  }
  build() {    Column() {      this.componentBuilder()      Child({ aBuilder0: this.componentBuilder })    }  }}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_android_02

使用场景

参数初始化组件

@BuilderParam装饰的方法可以是有参数和无参数的两种形式,需与指向的@Builder方法类型匹配。@BuilderParam装饰的方法类型需要和@Builder方法类型一致。

@Builder function GlobalBuilder1($$ : {label: string }) {  Text($$.label)    .width(400)    .height(50)    .backgroundColor(Color.Green)}
@Componentstruct Child {  label: string = 'Child'  // 无参数类,指向的componentBuilder也是无参数类型  @BuilderParam aBuilder0: () => void;  // 有参数类型,指向的GlobalBuilder1也是有参数类型的方法  @BuilderParam aBuilder1: ($$ : { label : string}) => void;
  build() {    Column() {      this.aBuilder0()      this.aBuilder1({label: 'global Builder label' } )    }  }}
@Entry@Componentstruct Parent {  label: string = 'Parent'
  @Builder componentBuilder() {    Text(`${this.label}`)  }
  build() {    Column() {      this.componentBuilder()      Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 })    }  }}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_华为_03

尾随闭包初始化组件

在自定义组件中使用@BuilderParam装饰的属性时也可通过尾随闭包进行初始化。在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。

说明

此场景下自定义组件内有且仅有一个使用@BuilderParam装饰的属性。

开发者可以将尾随闭包内的内容看做@Builder装饰的函数传给@BuilderParam。示例如下:

// xxx.ets@Componentstruct CustomContainer {  @Prop header: string;  @BuilderParam closer: () => void
  build() {    Column() {      Text(this.header)        .fontSize(30)      this.closer()    }  }}
@Builder function specificParam(label1: string, label2: string) {  Column() {    Text(label1)      .fontSize(30)    Text(label2)      .fontSize(30)  }}
@Entry@Componentstruct CustomContainerUser {  @State text: string = 'header';
  build() {    Column() {      // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包      // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数      CustomContainer({ header: this.text }) {        Column() {          specificParam('testA', 'testB')        }.backgroundColor(Color.Yellow)        .onClick(() => {          this.text = 'changeHeader';        })      }    }  }}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_分类_04

最后

这里整理了一份《鸿蒙零基础入门学习指南》,希望能对那些想要学习鸿蒙,但是有没有方向的人提供一点帮助。本文档适用于HarmonyOS应用开发的初学者(由于文档内容过多,因此为了避免影响到大家的阅读体验,在此只以截图展示部分内容,详细完整版的看文末有免费的获取方式!)

《鸿蒙零基础入门学习指南》

目录

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_分类_05

一、快速入门

适用于HarmonyOS应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉HarmonyOS应用开发流程。

  • 开发准备
  • 基本概念
  • 工具准备
  • 构建第一个ArkTS应用(Stage模型)
  • 构建第一个ArkTS应用(FA模型)
  • 构建第一个JS应用(FA模型)

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_学习_06

二、开发基础知识

  • 应用程序包基础知识
  • 应用程序包概述
  • 应用程序包结构
  • 应用程序包多HAP机制
  • 应用程序包安装和卸载流程
  • 应用程序包更新流程
  • 共享包
  • 应用程序包快速修复
  • 应用配置文件(Stage模型)
  • 应用配置文件概述(Stage模型)
  • app.json5配置文件
  • module.json5配置文件
  • 应用配置文件概述(FA模型)
  • 应用配置文件概述(FA模型)
  • app对象内部结构
  • deviceConfig内部结构
  • module对象内部结构

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_华为_07

三、资源分类与访问

应用开发过程中,经常需要用到颜色、字体、间距、图片等资源,在不同的设备或配置中,这些资源的值可能不同。

  • 资源分类与访问
  • 资源分类
  • 资源目录
  • 资源组目录
  • 创建资源目录和资源文件
  • 创建资源目录和资源文件
  • 创建资源目录
  • 创建资源文件
  • 资源访问
  • 应用资源
  • 系统资源
  • 资源匹配

四、学习ArkTs语言

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在 TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。

  • 初识ArkTS语言
  • 基本语法
  • 基本语法概述
  • 声明式UI描述
  • 自定义组件
  • 状态管理
  • 其他状态管理
  • 其他状态管理概述
  • @Watch装饰器:状态变量更改通知
  • $$语法:内置组件双向同步
  • 渲染控制
  • 渲染控制概述
  • if/else:条件渲染
  • ForEach:循环渲染
  • LazyForEach:数据懒加载

鸿蒙开发入门:自定义组件--@BuilderParam装饰器_harmonyos_08


|