摘要
在鴻蒙(HarmonyOS)應用開發中,實時數據更新是一個繞不開的話題,尤其是在你封裝了很多自定義組件、需要多個組件之間共享和同步數據的場景里。過去我們可能會依賴父子組件直接傳參或全局狀態管理,但這樣寫會讓代碼變得復雜、不易維護。鴻蒙提供了 @Observed 和 @ObjectLink 裝飾器,幫我們優雅地實現數據的實時更新和組件聯動,開發體驗非常順滑。
引言
現在的鴻蒙應用場景越來越復雜,比如電商的商品詳情和購物車同步、聊天應用的實時消息刷新、IoT 應用中的設備狀態變更。這些都要求數據能在不同組件間實時更新,而且不能為了同步狀態寫一堆“搬運代碼”。
在日常開發中,@Observed 負責讓一個類的實例具備“可觀察”的能力,一旦數據變化,引用它的組件就會自動刷新。@ObjectLink 則讓子組件能夠直接“訂閱”父組件傳下來的對象變化,而不需要手動再寫回調去同步。
下面我們通過一個可運行的 Demo,把這套機制講清楚。
用 @Observed + @ObjectLink 實現實時數據更新
基本原理
- @Observed:讓一個類的實例變成可觀察對象,當它的屬性發生變化時,會通知引用它的 UI 組件重新渲染。
- @ObjectLink:用于子組件屬性綁定,讓子組件可以感知父組件傳入的對象變化。
代碼示例
// ViewModel.ts
@Observed
export class MyViewModel {title: string = ""constructor(title: string) {this.title = title}
}// OtherComponent.ets
@Component
export struct OtherComponent {@ObjectLink vm: MyViewModelbuild() {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。
@Observed
export class CartItem {count: number = 1
}@Component
export struct ProductDetail {@ObjectLink item: CartItembuild() {Column() {Button("增加數量").onClick(() => this.item.count++)}}
}@Component
export struct CartBar {@ObjectLink item: CartItembuild() {Text("數量: " + this.item.count)}
}
場景 2:聊天應用的實時消息
描述:在聊天頁面發送消息,消息列表組件應當實時刷新。
實現思路:
- 用
@Observed
包裝一個MessageList
,內部是一個數組。 - 消息輸入框組件發送消息后,直接修改
MessageList
,消息列表組件自動更新。
@Observed
class MessageList {messages: string[] = []
}@Component
struct ChatInput {@ObjectLink msgList: MessageListbuild() {Button("發送").onClick(() => {this.msgList.messages.push("新消息 " + Date.now())})}
}@Component
struct ChatList {@ObjectLink msgList: MessageListbuild() {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 應用,這套模式都能極大減少代碼量,提高可維護性。
如果你現在的項目中有多個自定義組件需要共享數據,這套方法可以直接用起來,幾乎不需要額外改動架構。