HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新

摘要

在鸿蒙(HarmonyOS)应用开发中,实时数据更新是一个绕不开的话题,尤其是在你封装了很多自定义组件、需要多个组件之间共享和同步数据的场景里。过去我们可能会依赖父子组件直接传参或全局状态管理,但这样写会让代码变得复杂、不易维护。鸿蒙提供了 @Observed 和 @ObjectLink 装饰器,帮我们优雅地实现数据的实时更新和组件联动,开发体验非常顺滑。

引言

现在的鸿蒙应用场景越来越复杂,比如电商的商品详情和购物车同步、聊天应用的实时消息刷新、IoT 应用中的设备状态变更。这些都要求数据能在不同组件间实时更新,而且不能为了同步状态写一堆"搬运代码"。

在日常开发中,@Observed 负责让一个类的实例具备"可观察"的能力,一旦数据变化,引用它的组件就会自动刷新。@ObjectLink 则让子组件能够直接"订阅"父组件传下来的对象变化,而不需要手动再写回调去同步。

下面我们通过一个可运行的 Demo,把这套机制讲清楚。

基本原理

  • @Observed:让一个类的实例变成可观察对象,当它的属性发生变化时,会通知引用它的 UI 组件重新渲染。
  • @ObjectLink:用于子组件属性绑定,让子组件可以感知父组件传入的对象变化。

代码示例

ts 复制代码
// ViewModel.ts
@Observed
export class MyViewModel {
  title: string = ""
  constructor(title: string) {
    this.title = title
  }
}

// OtherComponent.ets
@Component
export struct OtherComponent {
  @ObjectLink vm: MyViewModel

  build() {
    Row() {
      Text(this.vm.title)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin(10)
    }
    .width("100%")
    .height(60)
    .backgroundColor("#eeeeee")
    .justifyContent(FlexAlign.Center)
    .alignItems(VerticalAlign.Center)
  }
}

// MyComponent.ets
@Entry
@Component
export struct MyComponent {
  @State vm: MyViewModel = new MyViewModel("初始标题")

  build() {
    Column() {
      OtherComponent({ vm: this.vm })
        .onClick(() => {
          this.vm.title = "标题已更新 " + new Date().toLocaleTimeString()
        })

      Button("点击更新标题")
        .margin(10)
        .onClick(() => {
          this.vm.title = "按钮触发更新 " + new Date().toLocaleTimeString()
        })
    }
    .width("100%")
    .height("100%")
  }
}

代码解析

MyViewModel

  • 用 @Observed 修饰,让它的属性具备响应式更新能力。
  • 改变 title 会自动触发 UI 组件刷新。

OtherComponent

  • 用 @ObjectLink 接收父组件传入的 vm,并实时订阅它的变化。
  • 不需要手动写事件监听,只要数据变化,UI 就会刷新。

MyComponent

  • 用 @State 声明一个可响应的 MyViewModel 实例,并传给子组件。
  • 父组件点击区域或者按钮都会修改 vm.title,从而触发子组件刷新。

场景应用

场景 1:商品详情与购物车同步

描述:在电商应用中,用户在商品详情页修改购买数量,购物车组件的数量显示也需要立刻变化。

实现思路:

  • 将商品数量信息放到一个 @Observed 的 ViewModel 中。
  • 详情页和购物车组件通过 @ObjectLink 共享这个 ViewModel。
ts 复制代码
@Observed
export class CartItem {
  count: number = 1
}

@Component
export struct ProductDetail {
  @ObjectLink item: CartItem
  build() {
    Column() {
      Button("增加数量")
        .onClick(() => this.item.count++)
    }
  }
}

@Component
export struct CartBar {
  @ObjectLink item: CartItem
  build() {
    Text("数量: " + this.item.count)
  }
}

场景 2:聊天应用的实时消息

描述:在聊天页面发送消息,消息列表组件应当实时刷新。

实现思路:

  • 用 @Observed 包装一个 MessageList,内部是一个数组。
  • 消息输入框组件发送消息后,直接修改 MessageList,消息列表组件自动更新。
ts 复制代码
@Observed
class MessageList {
  messages: string[] = []
}

@Component
struct ChatInput {
  @ObjectLink msgList: MessageList
  build() {
    Button("发送")
      .onClick(() => {
        this.msgList.messages.push("新消息 " + Date.now())
      })
  }
}

@Component
struct ChatList {
  @ObjectLink msgList: MessageList
  build() {
    Column() {
      ForEach(this.msgList.messages, (msg) => Text(msg))
    }
  }
}

场景 3:IoT 设备状态面板

描述:多个组件显示同一设备的温度、湿度、电池电量,任意组件更新数据时其他组件同步变化。

实现思路:

  • 用 @Observed 包装 DeviceStatus 对象。
  • 传递给各个子组件,通过 @ObjectLink 绑定。

QA 环节

Q1:@Observed 和 @State 有什么区别?

  • @Observed 用于类的实例,使它变成可观察对象,适合跨组件共享。
  • @State 用于组件内的变量,适合管理本地状态。

Q2:为什么要用 @ObjectLink,而不是直接传值?

  • 直接传值是浅拷贝,不会触发子组件刷新。
  • @ObjectLink 会建立对象引用,保证数据变化实时传递。

Q3:如果多个组件要共享数据,该怎么组织?

  • 建议抽一个 ViewModel,用 @Observed 修饰,在需要的地方通过 @ObjectLink 引用。

总结

在鸿蒙应用开发中,@Observed + @ObjectLink 是处理实时数据更新的"黄金搭档"。它们的组合能让我们轻松在多个组件间同步数据,而不用手动写一堆事件监听或状态同步逻辑。在实际项目中,不管是电商、聊天还是 IoT 应用,这套模式都能极大减少代码量,提高可维护性。

如果你现在的项目中有多个自定义组件需要共享数据,这套方法可以直接用起来,几乎不需要额外改动架构。

相关推荐
梦想不只是梦与想7 小时前
HarmonyOS应用分层架构设计
harmonyos·分层架构·一次开发,多端部署
MardaWang10 小时前
当滚动逃离了框架 ——HarmonyOS Web 与原生混排滚动的冲突本质与解法
harmonyos·arkts·鸿蒙·deveco studio
tsqtsqtsq030911 小时前
DevEco Studio 介绍
harmonyos
HwJack2014 小时前
【共创稿事节】HarmonyOS 7文旅展陈展厅大空间 3DGS 重建的分块策略与拼接踩坑
3d·华为·harmonyos
熊猫钓鱼>_>16 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 kotlin-inject 实现依赖注入适配
开发语言·华为·kotlin·ai编程·inject·鸿蒙·openharmony
m0_7381858216 小时前
Flutter 鸿蒙化实战:media_info 适配 OpenHarmony,媒体信息与缩略图
flutter·华为·harmonyos·鸿蒙·媒体
m0_7381858217 小时前
Flutter 鸿蒙化实战:just_audio 适配 OpenHarmony,功能强大的播放器
flutter·华为·harmonyos·鸿蒙
翼辉cto17 小时前
Kotlin Multiplatform 三方库 SQLDelight 的 OpenHarmony 鸿蒙化适配实战
开发语言·kotlin·harmonyos
SuperHeroWu717 小时前
TraeCode 国内版接入 DevEco CLI:用官方知识开发鸿蒙应用
ai编程·harmonyos·知识库·trae·aicoding·skills·deveco cli