在鸿蒙 HarmonyOS ArkTS 开发中,@Builder 装饰器用于自定义UI组件复用,能大幅减少页面重复代码。但很多开发者在使用时,都会遇到参数传递后UI不刷新的问题——这本质是没掌握 @Builder参数传递规则

本文带你彻底吃透 @Builder 方法的按值传递按引用传递机制,结合完整可运行Demo,解决参数传递后UI不刷新的经典坑点!

📌 本文核心:@Builder参数传递规则 + 值传递/引用传递区别 + UI刷新原理 + 实战演示

一、前言

@Builder 是ArkTS中非常实用的UI复用工具,允许我们将一段UI结构封装成方法,多处调用。
但它的参数传递机制与普通方法不同,直接决定了状态变量变化时,UI是否会自动刷新

这是新手最容易踩坑的知识点,也是面试高频考点。


二、@Builder 方法参数传递核心规则

@Builder 方法只有 两种参数传递机制按值传递按引用传递

终极判断规则

  1. 只有一个参数 + 参数是【对象字面量】按引用传递
  2. 其余所有情况一律按值传递

刷新机制差异

  • 按引用传递:参数是状态变量时,变量变化 → UI自动刷新
  • 按值传递:参数是状态变量时,变量变化 → UI不刷新

三、两种传递机制详细说明

1. 按值传递(默认机制)

  • 格式:传递普通类型(number/string/boolean等)
  • 特点:传递的是变量副本,方法内部无法感知外部变量变化
  • UI刷新:状态变量改变,不会触发@Builder内部UI更新

2. 按引用传递(特殊规则)

  • 格式:必须是单个参数 + 对象字面量
  • 特点:传递的是对象引用,与外部状态变量指向同一块内存
  • UI刷新:状态变量改变,@Builder内部UI自动同步更新

四、完整实战代码

通过计数器案例,直观看到值传递不刷新、引用传递自动刷新的效果。

// 1. 定义对象类型(推荐使用interface规范类型)
interface ObjType {
  count: number;
}

@Entry
@Component
struct BuilderParameterPage {
  // 状态变量:计数
  @State count: number = 0;

  build() {
    Column({ space: 50 }) {
      // 原始文本(正常刷新)
      Text(`当前计数: ${this.count}`)
        .fontSize(35)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.Blue)

      // ==========================================
      // 1. 按值传递:数字类型 → 状态变化不刷新
      // ==========================================
      valueTextBuilder(this.count)

      // ==========================================
      // 2. 按引用传递:单个对象参数 → 自动刷新
      // ==========================================
      referenceTextBuilder({ count: this.count })

      // 计数器按钮
      Row({ space: 50 }) {
        Button('-1')
          .width(80)
          .onClick(() => this.count--)

        Button('+1')
          .width(80)
          .onClick(() => this.count++)
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

// ==========================================
// @Builder 1:按值传递(普通参数)
// 特点:count变化 → UI不刷新
// ==========================================
@Builder
function valueTextBuilder(count: number) {
  Text(`按值传递: ${count}`)
    .fontSize(30)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.Red)
}

// ==========================================
// @Builder 2:按引用传递(单个对象参数)
// 特点:count变化 → UI自动刷新
// ==========================================
@Builder
function referenceTextBuilder(obj: ObjType) {
  Text(`按引用传递: ${obj.count}`)
    .fontSize(30)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.Green)
}

五、运行效果说明(一眼看懂区别)

点击 +/- 按钮修改 count

  • 原始文本 正常刷新
  • 按值传递文本 保持不变(不刷新)
  • 按引用传递文本 实时同步刷新

六、关键知识点补充

1. 为什么要使用 interface 定义对象类型?

在ArkTS/TypeScript中:

  • 对象字面量不能直接作为类型声明
  • 必须使用 interfacetype 关键字定义类型
  • 代码更规范、类型检查更严格

2. 引用传递的固定写法

必须满足:

// 定义
interface 类型名 {
  属性: 类型
}

@Builder
function 方法名(参数: 类型名) { ... }

// 调用
方法名({ 属性: 状态变量 })

七、总结(必记3句话)

  1. @Builder 参数只有两种传递方式:值传递 + 引用传递
  2. 单个对象参数 = 引用传递(UI可刷新)
  3. 其他所有情况 = 值传递(UI不刷新)

只要记住这个规则,你在鸿蒙开发中使用 @Builder 装饰器将再也不会遇到UI不更新的问题!

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐