一、引言

在鸿蒙(HarmonyOS)应用开发中,状态管理是构建动态、可交互界面的核心。随着 API 12 及后续版本对 @ComponentV2 装饰器的引入,状态管理变得更加简洁和高效。其中,@Param 装饰器是子组件接收父组件数据的关键桥梁。

二、什么是 @Param?

@Param 是鸿蒙状态管理 V2 版本(@ComponentV2)中用于接收外部传入数据的装饰器。它的核心作用是让子组件能够从父组件获取单向同步的数据。当父组件的数据源发生变化时,子组件中对应 @Param 装饰的变量会自动更新并刷新 UI。

2.1 核心特点

  • 单向数据流:数据只能从父组件流向子组件,子组件不能直接修改 @Param 变量(只读)。若需要修改,可搭配 @Event@Once 使用。
  • 灵活初始化:支持本地默认值,但若从父组件传入了值,则优先使用外部传入的值。未初始化时必须配合 @Require 使用,强制要求外部传入。
  • 广泛的数据类型支持:可以装饰 numberstringbooleanObjectclassArraySetMapDate 等,也支持 nullundefined 和联合类型。
  • 简化 V1 状态管理:相比 V1 的 @Prop@Link@ObjectLink 等装饰器,@Param 使用方式更统一,减少了选择困难和性能问题。

三、基础用法:从父组件传递数据

下面通过一个简单的计数器示例,展示 @Param 的基本用法。

3.1 父组件:定义状态并传递

父组件使用 @Local 定义本地状态,并通过子组件的构造参数将数据传递下去。

// 父组件
@Entry
@ComponentV2
struct Parent {
  @Local count: number = 0;

  build() {
    Column() {
      Text(`父组件 count: ${this.count}`)
        .fontSize(20)
      Button('增加')
        .onClick(() => {
          this.count++;
        })
      Child({ value: this.count })   // 将 count 传入子组件
    }
    .width('100%')
    .height('100%')
  }
}

3.2 子组件:使用 @Param 接收数据

子组件使用 @Require @Param 声明一个必须从外部传入的属性。

// 子组件
@ComponentV2
struct Child {
  @Require @Param value: number;   // 必须从外部传入

  build() {
    Column() {
      Text(`子组件接收的 value: ${this.value}`)
        .fontSize(20)
        .onClick(() => {
          // ❌ Cannot assign to 'value' because it is a read-only property. <ArkTSCheck>
          // this.value = 1;
        })
    }
  }
}

3.3 运行效果

在这里插入图片描述

每次点击父组件中的“增加”按钮,count 增加,子组件中 value 的显示会随之更新。

重点:子组件内无法对 this.value 重新赋值(尝试赋值会报编译错误),保证了数据流的单向性和可预测性。

上面示例中传递的是基本数据类型,如需传递引用数据类型,需要配合 @ObservedV2 + @Trace

四、进阶用法:@Once 与 @Event

4.1 @Once:仅初始化时接收

若只需在初始化时接收一次值,后续不再随父组件更新,可搭配 @Once 使用。

@Once 是鸿蒙状态管理 V2 中与 @Param 配合使用的装饰器,用于标记某个参数仅在组件初始化时接收一次父组件传入的值。一旦组件创建完成,即使父组件的数据源后续发生变化,子组件中 @Once 装饰的变量也不会再更新,从而避免不必要的 UI 刷新,提升性能。

@ComponentV2
struct Child {
  @Param @Once initialValue: string = "默认值";

  build() {
    Text(this.initialValue)
  }
}

4.2 @Event:子组件通知父组件修改

若需要在子组件内修改外部数据,可通过 @Event 装饰回调函数,让子组件“通知”父组件执行修改,从而保持数据和 UI 的一致性。

@Event 是鸿蒙状态管理 V2 中用于定义事件回调的装饰器。它允许父组件将方法作为回调传递给子组件,子组件通过调用该回调来“通知”父组件执行修改操作,从而在保持单向数据流的前提下实现子组件对父组件数据的间接修改。

// 父组件
@Entry
@ComponentV2
struct Parent {
  @Local count: number = 0;

  // 定义一个修改 count 的方法
  incrementCount() {
    this.count++;
  }

  build() {
    Column() {
      Text(`父组件 count: ${this.count}`)
      Child({ value: this.count, onIncrement: () => {
        this.incrementCount()
      } })
    }
  }
}

// 子组件
@ComponentV2
struct Child {
  @Require @Param value: number;
  @Require @Event onIncrement: () => void; // 接收一个事件回调

  build() {
    Column() {
      Text(`子组件 value: ${this.value}`)
      Button('子组件请求增加')
        .onClick(() => {
          this.onIncrement(); // 调用父组件的方法
        })
    }
  }
}

五、使用提示与最佳实践

  • 优先使用 @Param:在 V2 架构中,@Param 是子组件接收外部数据的首选方式,它比 V1 的 @Prop 更简洁、性能更好。
  • 配合 @Require 使用:如果 @Param 变量没有设置默认值,必须加上 @Require 装饰器,强制父组件传入该参数,避免运行时错误。
  • 避免在子组件内修改 @Param:保持数据流的单向性,有助于代码的可维护性和可预测性。如需修改,请使用 @Event 回调。
  • 合理使用 @Once:对于只需要初始化一次的数据(如配置项、静态文本),使用 @Once 可以避免不必要的 UI 刷新,提升性能。

六、总结

@Param 是鸿蒙 @ComponentV2 状态管理体系中的基石。它通过强制单向数据流,让组件间的数据传递变得清晰、可预测。结合 @Once@Event,你可以构建出既灵活又健壮的组件树。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐