一、MVVM模式概述
在鴻蒙Next的ArkUI框架中,MVVM(Model-View-ViewModel)模式是一種重要的架構(gòu)模式击费,用于管理應(yīng)用程序中的數(shù)據(jù)和UI之間的交互椰拒。MVVM模式通過將數(shù)據(jù)和視圖分離,使得應(yīng)用程序的開發(fā)更加高效侦镇、可維護(hù)和可測試。
(一)MVVM模式的組成部分
- Model層:存儲數(shù)據(jù)和相關(guān)邏輯的模型织阅,表示組件或其他相關(guān)業(yè)務(wù)邏輯之間傳輸?shù)臄?shù)據(jù)壳繁,是對原始數(shù)據(jù)的進(jìn)一步處理。
- View層:在ArkUI中通常是@Component裝飾組件渲染的UI荔棉,負(fù)責(zé)展示數(shù)據(jù)給用戶闹炉。
- ViewModel層:在ArkUI中,ViewModel是存儲在自定義組件的狀態(tài)變量润樱、LocalStorage和AppStorage中的數(shù)據(jù)渣触,起到數(shù)據(jù)與視圖綁定的作用,負(fù)責(zé)處理數(shù)據(jù)的獲取壹若、更新和通知視圖的變化嗅钻。
(二)MVVM模式的工作原理
- 自定義組件通過執(zhí)行其build()方法或者@Builder裝飾的方法來渲染UI,即ViewModel可以渲染View舌稀。
- View可以通過相應(yīng)event handler來改變ViewModel啊犬,即事件驅(qū)動ViewModel的改變,另外ViewModel提供了@Watch回調(diào)方法用于監(jiān)聽狀態(tài)數(shù)據(jù)的改變壁查。
- 在ViewModel被改變時觉至,需要同步回Model層,以保證ViewModel和Model的一致性睡腿,即應(yīng)用自身數(shù)據(jù)的一致性语御。
(三)ViewModel結(jié)構(gòu)設(shè)計的目的
ViewModel結(jié)構(gòu)設(shè)計應(yīng)始終為了適配自定義組件的構(gòu)建和更新峻贮,將Model和ViewModel分開的原因在于,目前很多關(guān)于UI構(gòu)造和更新的問題应闯,都是由于ViewModel的設(shè)計沒有很好地支持自定義組件的渲染纤控,或者試圖讓自定義組件強行適配Model層,而中間沒有用ViewModel來進(jìn)行分離碉纺。例如船万,直接將SQL數(shù)據(jù)庫中的數(shù)據(jù)讀入內(nèi)存這種數(shù)據(jù)模型不能很好地直接適配自定義組件的渲染,所以在應(yīng)用程序開發(fā)中需要適配ViewModel層骨田。
二耿导、ViewModel的數(shù)據(jù)源
(一)數(shù)據(jù)源類型及共享范圍
- @State:組件級別的共享,通過命名參數(shù)機制傳遞态贤,例如:CompA: ({ aProp: this.aProp })舱呻,表示傳遞層級(共享范圍)是父子之間的傳遞∮破可以初始化多種狀態(tài)變量箱吕,@Prop、@Link和@ObjectLink可以和其建立單向或雙向同步柿冲。
- @Provide:組件級別的共享茬高,可以通過key和@Consume綁定,因此不用參數(shù)傳遞姻采,實現(xiàn)多層級的數(shù)據(jù)共享雅采,共享范圍大于@State。適合在單個頁面UI組件樹中共享狀態(tài)數(shù)據(jù)慨亲。
- LocalStorage:頁面級別的共享,可以通過@Entry在當(dāng)前組件樹上共享LocalStorage實例宝鼓,可在ArkUI應(yīng)用程序的幾個頁面上共享刑棵。
- AppStorage:應(yīng)用全局的UI狀態(tài)存儲,和應(yīng)用進(jìn)程綁定愚铡,在整個應(yīng)用內(nèi)的狀態(tài)數(shù)據(jù)的共享蛉签。是LocalStorage的單例對象,在頁面中使用@StorageLink和@StorageProp為多個頁面之間共享數(shù)據(jù)沥寥,還可使用PersistentStorage將其特定屬性持久化到本地磁盤文件中碍舍,再次啟動時恢復(fù)數(shù)據(jù)。
(二)不同數(shù)據(jù)源的使用示例
-
@State裝飾的變量與子組件共享狀態(tài)數(shù)據(jù)
- 例如在
Parent
組件中使用@State
裝飾testNum
變量邑雅,并將其傳遞給LinkChild
和Sibling
子組件片橡。在LinkChild
組件中,@Link
裝飾的testNum
與父組件的@State testNum
建立雙向同步淮野,LinkChild
中的更改會同步到父組件Parent
捧书,再從Parent
同步到Sibling
吹泡,同時也會同步給LinkChild
的子組件LinkLinkChild
和PropLinkChild
。而PropLinkChild
中的@Prop
和其父組件建立單向同步關(guān)系经瓷。
- 例如在
-
@Provide裝飾的變量與后代組件共享狀態(tài)數(shù)據(jù)
- 如在
Parent
組件中使用@Provide
裝飾testNum
變量爆哑,在LinkChild
、Sibling
舆吮、LinkLinkChild
等后代組件中使用@Consume
創(chuàng)建雙向同步揭朝,通過綁定相同的key連接,而不是通過組件構(gòu)造函數(shù)參數(shù)傳遞色冀,將更改從父組件傳遞到孫子組件更加方便潭袱。
- 如在
-
給LocalStorage實例中對應(yīng)的屬性建立雙向或單向同步
- 創(chuàng)建
LocalStorage
實例并通過@Entry(storage)
注入根節(jié)點,在Parent
組件中初始化@LocalStorageLink("testNum")
變量呐伞,會在LocalStorage
實例中創(chuàng)建testNum
屬性并設(shè)置初始值敌卓。其子組件使用@LocalStorageLink
或@LocalStorageProp
綁定同一個屬性名key來傳遞數(shù)據(jù),@LocalStorageLink
和LocalStorage
中對應(yīng)屬性的同步行為與@State
和@Link
一致伶氢,為雙向數(shù)據(jù)同步趟径。
- 創(chuàng)建
-
給AppStorage中對應(yīng)的屬性建立雙向或單向同步
- 與
LocalStorage
類似,在組件中使用@StorageLink
和@StorageProp
為多個頁面之間共享數(shù)據(jù)癣防,如在Parent
蜗巧、LinkChild
、Sibling
等組件中使用@StorageLink("testNum")
或@StorageProp("testNum")
來共享和操作AppStorage
中的testNum
屬性蕾盯。
- 與
三幕屹、ViewModel的嵌套場景
(一)處理復(fù)雜類型數(shù)據(jù)
大多數(shù)情況下,ViewModel數(shù)據(jù)項是復(fù)雜類型级遭,如對象數(shù)組望拖、嵌套對象或其組合。對于嵌套場景挫鸽,使用@Observed搭配@Prop或者@ObjectLink來觀察變化说敏。推薦設(shè)計單獨的自定義組件來渲染每一個數(shù)組或?qū)ο螅瑢τ陬惡蛿?shù)組丢郊,@State盔沫、@Prop、@Link枫匾、@ObjectLink裝飾的變量只能觀察到第一層的變化架诞,若要觀察嵌套類內(nèi)部對象的變化,可使用@ObjectLink或@Prop干茉,優(yōu)先考慮@ObjectLink谴忧,其通過嵌套對象內(nèi)部屬性的引用初始化自身,性能更好,@Prop會對嵌套內(nèi)部對象進(jìn)行深度拷貝來初始化俏蛮,實現(xiàn)單向同步撑蚌,但性能較慢。
(二)@Prop和@ObjectLink嵌套數(shù)據(jù)結(jié)構(gòu)及區(qū)別
-
嵌套數(shù)據(jù)結(jié)構(gòu)示例
- 父組件
ViewB
渲染@State arrA
(Array<ClassA>
)搏屑,@State
可觀察新數(shù)組分配争涌、數(shù)組項插入、刪除和替換辣恋。子組件ViewA
渲染每個ClassA
對象亮垫,使用@ObjectLink a: ClassA
可觀察嵌套在Array
內(nèi)的ClassA
對象的變化(前提是ClassA
用@Observed
裝飾)。不使用@Observed
時伟骨,如ViewB
中this.arrA[Math.floor(this.arrA.length/2)].c = 10
的操作不會被觀察到饮潦,相應(yīng)ViewA
組件也不會更新。
- 父組件
-
@Prop和@ObjectLink的區(qū)別
- 當(dāng)在
ViewA
中將@ObjectLink
替換為@Prop
時携狭,@Prop
會對嵌套對象進(jìn)行深度拷貝初始化继蜡,性能慢,且在一個ViewA
中的屬性賦值this.a.c += 1
不會引發(fā)使用同一個ClassA
初始化的其他ViewA
的渲染更新逛腿,因為它們是不同的拷貝稀并。而@ObjectLink
通過引用共享對象,一個ViewA
中屬性改變會觸發(fā)所有引用該對象的ViewA
更新(前提是ClassA
用@Observed
裝飾)单默。
- 當(dāng)在
四碘举、MVVM模式在鴻蒙Next中的優(yōu)勢
(一)簡化UI設(shè)計和實現(xiàn)
通過ViewModel層的隔離,將UI與數(shù)據(jù)模型分離搁廓,使得UI的設(shè)計和實現(xiàn)更加簡單引颈,開發(fā)者可以專注于UI的展示邏輯,而不必關(guān)心數(shù)據(jù)的獲取和存儲細(xì)節(jié)境蜕。
(二)提高UI性能
MVVM模式能夠更高效地更新UI蝙场,當(dāng)數(shù)據(jù)發(fā)生變化時,只有相關(guān)的UI部分會被更新粱年,而不是整個UI重新渲染李丰,從而提高了應(yīng)用程序的響應(yīng)速度和性能。
(三)增強代碼的可維護(hù)性和可測試性
數(shù)據(jù)和視圖的分離使得代碼結(jié)構(gòu)更加清晰逼泣,易于維護(hù)和測試≈凼妫可以單獨對ViewModel層進(jìn)行單元測試拉庶,驗證數(shù)據(jù)的正確性和處理邏輯,同時也方便對UI層進(jìn)行單獨的測試和優(yōu)化秃励。
總之氏仗,鴻蒙Next的MVVM思想為應(yīng)用程序開發(fā)提供了一種有效的架構(gòu)模式,有助于提高開發(fā)效率、提升應(yīng)用性能和改善代碼質(zhì)量皆尔。開發(fā)者在實際應(yīng)用中應(yīng)合理利用MVVM模式的特性呐舔,根據(jù)具體需求選擇合適的數(shù)據(jù)源和處理嵌套數(shù)據(jù)結(jié)構(gòu)的方式,以構(gòu)建出高質(zhì)量的應(yīng)用程序慷蠕。