@Observed 和 @ObjectLink

装饰器作用
@Observed标记一个类为可观察对象,当类属性变化时触发UI更新(需配合@ObjectLink使用)
@ObjectLink在自定义组件中绑定被@Observed装饰的类实例,实现对象属性级别的响应式更新

二、典型使用场景

1. 嵌套对象属性更新

场景
当需要监听一个对象内部属性的变化时(如用户信息中的 address.city),直接使用 @State 无法触发更新,需借助 @Observed + @ObjectLink

示例代码

// 定义可观察类
@Observed
class User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

// 父组件
@Entry
@Component
struct ParentPage {
  @State user: User = new User('Alice', 25);

  build() {
    Column() {
      ChildComponent({ user: this.user }) // 传递对象
      Button('Increase Age')
        .onClick(() => {
          this.user.age++; // 修改嵌套属性
        })
    }
  }
}

// 子组件
@Component
struct ChildComponent {
  @ObjectLink user: User; // 绑定对象

  build() {
    Text(`Age: ${this.user.age}`) // 自动更新
  }
}

2. 数组元素属性更新

场景
监听数组中某个对象的属性变化(如待办列表项的完成状态)。

示例代码

@Observed
class TodoItem {
  id: number;
  text: string;
  completed: boolean;

  constructor(id: number, text: string) {
    this.id = id;
    this.text = text;
    this.completed = false;
  }
}

@Entry
@Component
struct TodoList {
  @State todos: TodoItem[] = [
    new TodoItem(1, 'Buy milk'),
    new TodoItem(2, 'Read book')
  ];

  build() {
    Column() {
      ForEach(this.todos, (item: TodoItem) => {
        TodoItemComponent({ item: item })
      })
    }
  }
}

@Component
struct TodoItemComponent {
  @ObjectLink item: TodoItem;

  build() {
    Row() {
      Text(this.item.text)
        .decoration({ type: this.item.completed ? TextDecorationType.LineThrough : TextDecorationType.None })
      Toggle({ type: ToggleType.Checkbox })
        .isOn(this.item.completed)
        .onChange((checked: boolean) => {
          this.item.completed = checked; // 直接修改数组元素属性
        })
    }
  }
}

3. 跨组件共享对象状态

场景
多个子组件需要共享并修改同一个对象的属性(如购物车的商品数量)。

示例代码

@Observed
class CartItem {
  id: number;
  name: string;
  quantity: number;

  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
    this.quantity = 1;
  }
}

@Entry
@Component
struct ShoppingCart {
  @State item: CartItem = new CartItem(1, 'iPhone');

  build() {
    Column() {
      Text(`Total: ${this.item.quantity}`)
      QuantityController({ item: this.item })
      AddToCartButton({ item: this.item })
    }
  }
}

// 数量控制器组件
@Component
struct QuantityController {
  @ObjectLink item: CartItem;

  build() {
    Row() {
      Button('-')
        .onClick(() => this.item.quantity--)
      Text(`${this.item.quantity}`)
      Button('+')
        .onClick(() => this.item.quantity++)
    }
  }
}

// 加入购物车按钮组件
@Component
struct AddToCartButton {
  @ObjectLink item: CartItem;

  build() {
    Button('Add to Cart')
      .onClick(() => {
        this.item.quantity = 1; // 重置数量
      })
  }
}

三、与其他状态管理方案对比

方案适用场景对象属性监听代码复杂度
@State简单值类型(string/number)
@Link父子组件间的双向绑定⭐⭐
@Observed + @ObjectLink嵌套对象/数组元素属性更新⭐⭐⭐
AppStorage全局简单状态⭐⭐

四、关键注意事项

  1. 必须成对使用

    • @ObjectLink 必须绑定被 @Observed 装饰的类实例。
  2. 避免循环引用

    @Observed
    class Node {
      child?: Node; // 危险!可能导致循环引用
    }
    
  3. 不可直接替换对象

    // 错误!@ObjectLink 不能重新赋值
    this.user = new User('Bob', 30);
    
    // 正确:修改属性
    this.user.name = 'Bob';
    this.user.age = 30;
    
  4. 性能优化

    • 对于深层次嵌套对象,建议使用 @Track 装饰需要监听的特定属性:

      @Observed
      class User {
        name: string;
        @Track age: number; // 仅监听 age 变化
      }
      

五、常见问题解决

问题:修改了对象属性但UI未更新
排查步骤

  1. 确认类是否被 @Observed 装饰
  2. 检查是否使用 @ObjectLink 绑定对象
  3. 确保直接修改属性值(而非替换整个对象)
  4. 使用 async 函数时,确认在 TaskPool 或主线程操作

通过合理使用 @Observed@ObjectLink,可以实现鸿蒙应用中复杂数据结构的精准响应式更新。

<think>好的,我现在需要帮助用户理解鸿蒙开发中的@Observed@ObjectLink装饰器的作用,并找出错误的描述选项。首先,我需要回顾用户提供的引用内容,分析每个引用的关键点,然后结合这些信息来判断哪个选项是错误的。 根据用户提供的引用内容: 引用[1]指出在子组件中给@ObjectLink装饰的变量赋值是不允许的,并给出了反例。这说明@ObjectLink变量在子组件中是只读的,不能直接修改。 引用[2]提到在子组件中尝试给@ObjectLink变量赋值,如this.testNum = new Info(47),这会导致错误,进一步验证了引用[1]的内容。 引用[3]说明@ObjectLink用于接收@Observed类的实例,并与父组件中的状态变量建立双向绑定。这里强调@Observed装饰的类或属性,以及双向绑定的特性。 引用[4]讨论了@Provide@Consume的命名唯一性,与@Observed@ObjectLink无关,可能用于干扰选项。 接下来,用户的问题是关于这两个装饰器的作用解析及判断错误描述。假设用户提供的选项中可能包含以下几点: 1. @ObjectLink变量在子组件中可以修改。 2. @Observed装饰类,而@ObjectLink用于子组件建立双向绑定。 3. @ObjectLink只能用于基本数据类型。 4. @ObjectLink需要与父组件的@State变量绑定。 根据引用内容: - 错误描述可能是选项1,因为引用[1][2]明确禁止在子组件中修改@ObjectLink变量。 - 选项2正确,引用[3]支持。 - 选项3错误,因为@ObjectLink用于对象实例,而非基本类型。 - 选项4可能正确,因为需要父组件的对应状态变量,但需确认。 但用户提供的选项中是否包含这些需要推断。假设选项中有类似选项1的说法,则错误。例如,若选项A说“@ObjectLink允许子组件直接赋值”,则A错误。 总结:错误描述是允许在子组件中给@ObjectLink变量赋值。</think>### @Observed@ObjectLink装饰器作用解析 #### 核心功能说明 1. **@Observed装饰器** 用于标记类或类的属性,当被装饰的类属性发生变化时,会触发UI更新。例如: ```typescript @Observed class UserInfo { name: string; age: number; } ``` 此时若`UserInfo`实例的`name`或`age`变化,会通知绑定了该对象的组件更新[^3]。 2. **@ObjectLink装饰器** 在**子组件**中使用,用于接收父组件传递的`@Observed`类实例,并与之建立**单向同步**(非双向绑定)。 ```typescript @Component struct ChildComponent { @ObjectLink user: UserInfo; // 仅接受父组件传递的@Observed实例 } ``` **关键限制**:子组件中禁止直接对`@ObjectLink`变量赋值(如`this.user = new UserInfo()`),否则会报错[^1][^2]。 #### 错误描述判断 以下为典型错误描述: **错误选项示例**: > "子组件中可以通过`@ObjectLink`直接修改对象引用,例如`this.user = new UserInfo()`" **错误原因**: 根据引用[1]引用[2],子组件中给`@ObjectLink`变量赋值属于明确禁止的操作,只能通过父组件更新数据源。 #### 对比其他装饰器 | 装饰器 | 作用场景 | 数据流向
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值