ArkUI中的@builder装饰器(一)

目录

ArkUI中的装饰器概述

1.@Builder装饰器的用法

1.私有自定义构造函数

2.全局自定义构建函数

2.参数传递规则

1.值传递参数

2.引用传递      

3.限制条件

4.@Builder的使用场景

5.使用场景

1.代码复用

2.基于View-State的设计模式实现UI的刷新


ArkUI中的装饰器概述

        ArkUI提供轻量的UI元素复用机制@Builder,其内部UI结构固定,仅与使用方进行数据传递。开发者可将重复使用的UI元素抽象成函数,在build函数中调用。

        @Builder装饰的函数也称为"自定义构造函数"。

        它主要的优点如下:

        1.封装可以服用的UI结构,提高开发效率。

        2.保持内部组件变量的定义,还能完整管理组件的生命周期。

1.@Builder装饰器的用法

1.私有自定义构造函数

        我们可以在自己的Component中直接使用Builder修饰构建的函数。

        

        图1.私有自定义构造函数

        代码如下:

@Component
export struct BuilderExamplePage {
  @State label: string = 'Hello';
  pageInfos: NavPathStack = new NavPathStack();

  @Builder
  showTextBuilder() {
    // @Builder装饰此函数,使其能以链式调用的方式配置并构建Text组件
    Button("Hello",{type:ButtonType.Capsule})
      .fontSize(12)
      .fontWeight(FontWeight.Bold)
      .height(30)
      .width(100).margin({top:20})
  }

  @Builder
  showTextValueBuilder(param: string) {
    Button(param,{type:ButtonType.Capsule})
      .fontSize(12)
      .fontWeight(FontWeight.Bold)
      .height(30)
      .width(100).margin({top:20})
  }

  build() {
    NavDestination() {
      Column(){
        // 无参数
        this.showTextBuilder()
        // 有参数
        this.showTextValueBuilder('有参数按钮')
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Start)
    }
    .title('@builder装饰器用法').onReady((context: NavDestinationContext) => {
      this.pageInfos = context.pathStack;
    })
  }
}

2.全局自定义构建函数

        我们还以把一些UI中样式重复的UI组件单独提取出来,写在一个文件中:

@Builder
export  function NoParamCommonCapsuleButton() {
  // @Builder装饰此函数,使其能以链式调用的方式配置并构建Text组件
  Button("无参数按钮",{type:ButtonType.Capsule})
    .fontSize(12)
    .fontWeight(FontWeight.Bold)
    .height(30)
    .width(100).margin({top:20})
}

@Builder
export  function CommonCapsuleButton(message: string) {
  Button(message,{type:ButtonType.Capsule})
    .fontSize(12)
    .fontWeight(FontWeight.Bold)
    .height(30)
    .width(100).margin({top:20})
}

        然后在Component中直接使用:

  build() {
    NavDestination() {

      Column(){
        // 无参数
        this.showTextBuilder()
        // 有参数
        this.showTextValueBuilder('有参数按钮')
        CommonCapsuleButton("有参数按钮")
        NoParamCommonCapsuleButton()
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Start)
    }
    .title('@builder装饰器用法').onReady((context: NavDestinationContext) => {
      this.pageInfos = context.pathStack;
    })
  }

2.参数传递规则

1.值传递参数

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

        例如在上面的例子中,我们自定义的CommonCapsuleButton就是值传递,传一个参数之后,没有在外部修改这个参数。

2.引用传递      

        所以当使用状态变量的时候,推荐使用引用传递参数。

        按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder函数内的UI刷新。

       这里贴一下官方的一个demo,我已经运行过了。

class Tmp {
  paramA1: string = '';
}
@Builder
function overBuilder(params: Tmp) {
  Row() {
    Text(`UseStateVarByReference: ${params.paramA1} `)
  }
}
@Entry
@Component
struct Parent {
  @State label: string = 'Hello';
  build() {
    Column() {
      // 在父组件中调用overBuilder组件时,
      // 把this.label通过引用传递的方式传给overBuilder组件。
      overBuilder({ paramA1: this.label })
      Button('Click me').onClick(() => {
        // 单击Click me后,UI文本从Hello更改为ArkUI。
        this.label = 'ArkUI';
      })
    }
  }
}

3.限制条件

        使用@builder的时候,有一些限制条件:

  1. 1.@Builder装饰的函数内部不允许修改参数值,否则框架会抛出运行时错误。但开发者可以在使用@Builder的自定义组件中改变其参数。

  2. 2.@Builder按引用传递且仅传入一个参数时,才会触发动态渲染UI。

  3. 3.如果@Builder传入的参数是两个或两个以上,不会触发动态渲染UI,请参考@Builder存在两个或者两个以上参数

  4. 4.@Builder传入的参数中同时包含按值传递和按引用传递,不会触发动态渲染UI,请参考@Builder存在两个或者两个以上参数

  5. 5.@Builder的参数必须按照对象字面量的形式,把所需属性一一传入,才会触发动态渲染UI,请参考@Builder存在两个或者两个以上参数

4.@Builder的使用场景

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

5.使用场景

1.代码复用

        例如我们要实现如下的UI效果图:

        图3.登陆页面

    在实现底部的三种方式登陆排列的时候,我们可能会写下面的代码:

        Row({ space: 44 }) {
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($r('app.media.login_method1'))
          }
          .height('48vp')
          .width('48vp')
          .backgroundColor('#F1F3F5')
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($r('app.media.login_method2'))
          }
          .height('48vp')
          .width('48vp')
          .backgroundColor('#F1F3F5')
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($r('app.media.login_method3'))
          }
          .height('48vp')
          .width('48vp')
          .backgroundColor('#F1F3F5')
        }

        当我们使用@Builder之后,我们发现三种按钮样式相同,因此我们可以封装一个通用的方法。

  @Builder
  imageButton(src: Resource) {
    Button({ type: ButtonType.Circle, stateEffect: true }) {
      Image(src)
    }
    .height('48vp')
    .width('48vp')
    .backgroundColor('#F1F3F5')
  }

                然后UI中的代码变成了这样:

        Row({ space: 44 }) {
          this.imageButton($r('app.media.login_method1'))
          this.imageButton($r('app.media.login_method2'))
          this.imageButton($r('app.media.login_method3'))
        }

        这大大提高了我们的开发效率,设置这个函数我们还可以在其它页面被复用。

2.基于View-State的设计模式实现UI的刷新

        我们可以自定义组件中根据需要修改自定义构造函数,单独或者和其他装饰器一起实现UI刷新的效果。

<think>好的,我现在要处理用户关于鸿蒙系统中@Builder装饰器类型的询问。首先,我需要回忆下HarmonyOS的ArkUI框架,特别是关于装饰器的部分。记得@Builder有两种类型:全局的和自定义组件内的。用户可能想知道它们的区别和使用场景。 接下来,我需要确认这些信息是否正确。查阅官方文档,确认@Builder确实分为全局和组件内两种。全局的用@Builder直接装饰函数,不需要function关键字,可以在整个应用内使用;而组件内的则需要放在@Component装饰的类里,并且使用function关键字。这两者的作用域和访问权限不同,全局的无法访问组件私有属性,而组件内的可以。 然后,用户可能需要示例代码来理解两者的用法。我要确保代码符合规范,比如全局Builder的定义位置,以及组件内Builder的结构。同时,要指出关键点,比如参数传递的规则,特别是TS方法和@Builder参数传递的区别,比如是否需要按引用传递。 还要考虑用户可能遇到的问题,比如作用域的限制或样式继承的注意事项。例如,全局Builder的样式需要单独设置,而组件内的可以继承父组件的样式。这可能影响用户在设计UI时的选择。 生成相关问题的时候,需要覆盖常见的疑问点,比如两种类型的区别、参数传递规则、应用场景的选择、样式处理以及可能的设计考量。这样用户能全面了解@Builder的使用,并解决实际开发中的问题。 最后,确保回答结构清晰,分点说明,代码示例正确,并且引用标识正确添加。避免使用Markdown格式,保持自然的中文表达,同时符合用户的要求。</think>### HarmonyOS @Builder装饰器类型详解 在鸿蒙系统(HarmonyOS)的ArkUI框架中,@Builder装饰器用于创建可复用的UI组件构建函数,分为两种类型: #### 1. **全局@Builder** - **定义方式**:在`.ets`文件的全局作用域声明,无需`function`关键字 - **特点**: - 可跨文件调用 - 无法访问自定义组件的私有属性 - 需单独设置组件样式 ```typescript @Builder function GlobalBuilderExample() { Column() { Text('全局Builder') .fontSize(20) } } // 调用示例 GlobalBuilderExample() ``` #### 2. **自定义组件内@Builder** - **定义方式**:在`@Component`装饰的组件类内部声明,需添加`function`关键字 - **特点**: - 仅限当前组件使用 - 可访问组件内`this`作用域的成员变量 - 自动继承父组件样式 ```typescript @Component struct MyComponent { @State count: number = 0 @Builder function LocalBuilderExample() { Button(`点击次数 ${this.count}`) .onClick(() => { this.count++ }) } build() { Column() { this.LocalBuilderExample() } } } ``` #### ✨关键特性对比 | 类型 | 作用域 | 私有属性访问 | 样式继承 | |-----------|---------|--------|------| | 全局@Builder | 跨组件 | ❌ | ❌ | | 组件内@Builder | 当前组件内 | ✅ | ✅ | #### 参数传递规则 - 支持TS方法参数传递语法 - 必须使用**按引用传递**(`$$`符号)方式传递响应式变量: ```typescript @Builder function ParamBuilder($$: { message: string }) { Text($$.message) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值