HarmonyOS | 状态管理(五) | @Observed装饰器和@ObjectLink装饰器

本文详细介绍了HarmonyOS中的状态管理,特别是@Observed和@ObjectLink装饰器在处理嵌套对象和数组时的双向数据同步机制,以及它们的使用场景和限制条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

1.HarmonyOS | 状态管理(一) | @State装饰器
2.HarmonyOS | 状态管理(二) | @Prop装饰器
3.HarmonyOS | 状态管理(三) | @Link装饰器
4.HarmonyOS | 状态管理(四) | @Provide和@Consume装饰器



前言

学习到这里,我们之前只是学习了单个类或者属性状态的管理,现在我们这篇就讲讲多个类,数组,嵌套类的状态管理:@Observed装饰器和@ObjectLink装饰器


一、@ObjectLink和@Observed类装饰器用于哪些场景?

@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步

二、特性

  • @Observed 装饰的类,可以被 观察到属性的变化

  • 子组件@ObjectLink装饰器 装饰的状态变量用于 接收@Observed装饰的类的实例,和 父组件对应的状态变量 建立 双向数据绑定

  • 单独 使用 @Observed没有任何作用的,需要搭配 @ObjectLink 或者 @Prop 使用。

三、限制条件

  • 使用 @Observed 装饰class会 改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
  • @ObjectLink装饰器 不能@Entry装饰 的自定义组件中使用。

四、使用场景

1.观察变化和行为表现

观察的变化

class ClassA {
   
   
  public c: number;

  constructor(c: number) {
   
   
    this.c = c;
  }
}

@Observed
class ClassB {
   
   
  public a: ClassA;
  public b: number;

  constructor(a: ClassA, b: number) {
   
   
    this.a = a;
    this.b = b;
  }
}

行为表现

@ObjectLink b: ClassB

// 赋值变化可以被观察到
this.b.a = new ClassA(5)
this.b.b = 5

// ClassA没有被@Observed装饰,其属性的变化观察不到
this.b.a.c = 5

注:ClassB被@Observed装饰,其成员变量的赋值的变化是可以被观察到的,但对于ClassA,没有被@Observed装饰,其属性的修改不能被观察到。

2.嵌套对象

数据结构

// objectLinkNestedObjects.ets
let NextID: number = 1;

@Observed
class ClassA {
   
   
  public id: number;
  public c: number;

  constructor(c: number) {
   
   
    this.id = NextID++;
    this.c 
<think>嗯,用户之前已经问过关于20种常用装饰器的问题,特别是提到了HarmonyOS/ArkUI中的状态管理装饰器。现在他们希望更详细地了解这几个装饰器及其用法。我需要确保回答的结构清晰,分点说明每个装饰器的作用、使用场景以及示例代码。 首先,我需要回顾之前的回答,确认每个装饰器的基本信息是否正确,是否有遗漏或需要更新的地方。用户提到的装饰器包括@State、@Prop、@Link、@Watch、@Provide/@Consume、@Observed@ObjectLink。这些都属于ArkUI框架的状态管理部分,用于数据驱动UI更新,并且需要在组件内声明。 接下来,我需要详细展开每个装饰器的用途、使用方法注意事项。例如,@State用于组件内部状态,而@Prop用于父组件向子组件单向传递数据。需要解释它们之间的区别,比如@Prop是单向的,子组件不能修改,而@Link是双向的,修改会同步到父组件。@Watch用于监听变量变化,执行回调函数,这在需要处理状态变化后的逻辑时很有用。@Provide@Consume类似于React的Context,用于跨层级组件共享数据,可能需要说明它们的使用场景如何配对使用。 然后,@Observed@ObjectLink用于处理嵌套对象的更新,这里需要强调当对象属性变化时,如何通过装饰器让ArkUI检测到变化并更新UI。可能需要给出一个示例,说明如何用@Observed装饰类,然后用@ObjectLink在组件中绑定该类的实例属性。 在写作过程中,要确保每个部分都有清晰的标题,比如分点介绍每个装饰器,每个装饰器下面有用途说明、用法示例、注意事项等。代码示例要符合ArkUI的语法,可能需要使用TypeScript或ArkTS的语法结构,但用户之前的回答中代码示例是Python风格的,可能需要调整,但根据用户提供的上下文,之前的回答中代码示例可能混合了不同语言的风格,需要确认。不过根据HarmonyOS/ArkUI的文档,应该使用ArkTS(TypeScript的超集)的语法。 另外,用户可能对每个装饰器的实际应用场景感兴趣,需要举一些实际的例子,比如表单输入、组件间通信等。还要注意避免技术术语过于复杂,保持解释的易懂性,特别是如果用户可能是初学者的话。 需要检查是否有遗漏的装饰器,用户列出的七个装饰器是否全部涵盖。同时,是否需要比较不同装饰器之间的区别,比如@State@Link的区别,或者@Prop@Link的区别,以帮助用户更好地选择使用哪个装饰器。 最后,总结部分需要概括这些装饰器的共同目的,即实现数据驱动UI,以及如何根据不同的数据流需求选择合适的装饰器。可能还需要提到最佳实践,比如何时使用@Provide/@Consume而不是逐层传递props,或者如何处理复杂对象的状态管理。 确保回答结构清晰,每个装饰器独立成节,代码示例正确,并且注意事项部分能帮助用户避免常见错误。同时,语言要口语化,但保持专业性,符合用户要求的中文回答。</think>以下是 **HarmonyOS/ArkUI** 中状态管理装饰器的详细说明,涵盖核心用途、代码示例及使用场景: --- ### 一、 **@State** #### 用途 - **组件私有状态**:用于管理组件内部的状态变量,当状态变化时自动触发UI更新。 - **适用场景**:按钮点击计数、表单输入控制等组件内部状态管理。 #### 用法示例 ```typescript @Entry @Component struct MyComponent { @State count: number = 0 // 定义私有状态 build() { Column() { Text(`Count: ${this.count}`) Button('+1') .onClick(() => { this.count++ // 修改@State变量,触发UI刷新 }) } } } ``` #### 注意事项 - **初始化必须赋值**:`@State`变量需在声明时初始化(如`@State value: number = 0`)。 - **不可跨组件传递**:仅限当前组件内部使用。 --- ### 二、 **@Prop** #### 用途 - **单向数据流**:从父组件接收数据,子组件不能修改该值。 - **适用场景**:父组件向子组件传递只读数据(如配置参数)。 #### 用法示例 ```typescript // 子组件 @Component struct ChildComponent { @Prop message: string // 从父组件接收数据 build() { Text(this.message) } } // 父组件 @Entry @Component struct ParentComponent { @State parentMessage: string = "Hello from Parent" build() { Column() { ChildComponent({ message: this.parentMessage }) // 传递数据 Button('Change Parent Message') .onClick(() => { this.parentMessage = "Updated" // 父组件修改后,子组件@Prop自动更新 }) } } } ``` #### 注意事项 - **不可反向修改**:子组件尝试修改`@Prop`变量会触发编译错误。 --- ### 三、 **@Link** #### 用途 - **双向绑定**:与父组件共享状态,子组件修改会同步到父组件。 - **适用场景**:表单输入双向同步、组件间协同编辑。 #### 用法示例 ```typescript // 子组件 @Component struct ChildComponent { @Link inputText: string // 双向绑定父组件数据 build() { TextInput({ text: this.inputText }) .onChange((value: string) => { this.inputText = value // 修改@Link变量,父组件数据同步更新 }) } } // 父组件 @Entry @Component struct ParentComponent { @State text: string = "" build() { Column() { Text(`Parent Text: ${this.text}`) ChildComponent({ inputText: $text }) // 使用$符号传递引用 } } } ``` #### 注意事项 - **传递需用`$`符号**:父组件需通过`$variable`传递引用(如`$text`)。 --- ### 四、 **@Watch** #### 用途 - **监听状态变化**:当装饰的变量被修改时,触发回调函数。 - **适用场景**:数据变化后执行副作用(如保存到本地存储、发送网络请求)。 #### 用法示例 ```typescript @Entry @Component struct MyComponent { @State count: number = 0 @Watch('onCountChange') // 监听count变化,触发onCountChange @State watchedCount: number = 0 // 回调函数 onCountChange() { console.log(`Count changed to: ${this.count}`) } build() { Button('Add') .onClick(() => { this.count++ }) } } ``` #### 注意事项 - **需配合其他装饰器使用**:如`@State`或`@Link`。 --- ### 、 **@Provide / @Consume** #### 用途 - **跨层级数据共享**:祖先组件通过`@Provide`提供数据,后代组件通过`@Consume`获取,无需逐层传递。 - **适用场景**:主题切换、全局用户信息传递。 #### 用法示例 ```typescript // 祖先组件 @Entry @Component struct AncestorComponent { @Provide theme: string = "dark" // 提供数据 build() { Column() { ChildComponent() } } } // 后代组件 @Component struct ChildComponent { @Consume theme: string // 消费数据 build() { Text(`Current Theme: ${this.theme}`) .fontColor(this.theme === "dark" ? Color.White : Color.Black) } } ``` #### 注意事项 - **作用域内生效**:需在同一组件树层级中。 --- ### 六、 **@Observed@ObjectLink** #### 用途 - **嵌套对象监听**:`@Observed`装饰类,`@ObjectLink`绑定该类的实例属性,实现嵌套属性变化的UI更新。 - **适用场景**:对象内部属性变化(如`user.name`)。 #### 用法示例 ```typescript // 标记可观察的类 @Observed class User { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } // 父组件 @Entry @Component struct ParentComponent { @State user: User = new User("Alice", 30) build() { Column() { ChildComponent({ user: this.user }) Button('Change Name') .onClick(() => { this.user.name = "Bob" // 修改嵌套属性,触发子组件更新 }) } } } // 子组件 @Component struct ChildComponent { @ObjectLink user: User // 绑定被@Observed类的实例 build() { Text(`Name: ${this.user.name}`) } } ``` #### 注意事项 - **必须成对使用**:`@ObjectLink`必须绑定被`@Observed`装饰的类实例属性。 --- ### 七、 **选择装饰器的决策逻辑** | 场景 | 推荐装饰器 | |---------------------------------|------------------------| | 组件私有状态 | `@State` | | 父→子单向数据流 | `@Prop` | | 父子双向数据同步 | `@Link` | | 跨层级共享数据 | `@Provide` / `@Consume`| | 监听数据变化执行逻辑 | `@Watch` | | 对象内部属性更新 | `@Observed` + `@ObjectLink` | 通过合理组合这些装饰器,可以高效实现 **数据驱动UI** 的响应式开发模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谭祖爱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值