OpenHarmony—淺析ETS開發狀態管理
前言
本文主要是對于鴻蒙開發文檔 ETS 開發中的 UI狀態管理部分進行解讀和簡單的實踐,方便更快的切入開發工作,構建應用,對應文檔鏈接:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ts-ui-state-mgmt-concepts-0000001169868220。
鴻蒙狀態管理簡介
首先引用開發文檔中的圖片,圖片中已經基本可以看出整個應用中的數據流動,非常全面。
華為鴻蒙開發文檔對于應用中狀態的管理提供了豐富且全面的接口(僅提供通俗理解,具體定義見文檔):
- @State:用于定義應用管理的狀態,更像是React16.8之后的useState,方便代碼根據業務劃分邏輯,狀態定義僅支持class、number、boolean、string 及其組成的數組,并不允許object和any。
- @Props:單項數據流,父組件傳遞子組件,直接使用this.屬性名向下傳遞數據,子組件使用此修飾器接收,推薦用于只渲染的數據用此定義。
- @Link:雙向數據流,解決了vue中**emit**函數的功能,父組件用emit??函數的功能,父組件用向下傳遞數據,子組件使用此修飾器接收,推薦需要在子組件中修改父組件狀態的情況(即為類似于在vue中需要使用$emit)下使用。
- @Consume和**@Provide**: 其中provide是生產者,consume是消費者,寫過react的開發者應該對此很熟悉,類似于react中的context上下文,這一對修飾器主要實現的是上層組件跨多層傳值給下層組件,并實現雙向綁定數據。
- @Observed和**@ObjectLink**:其中@Observed用于修飾類,@ObjectLink用于在子組件中修飾已經被@Observed修飾的類對應的狀態(具體用法見下文),這一對修飾器主要解決的問題是,如果定義了一個包含多個對象(類)的數組,其中對象的屬性發生變化,能夠被應用監測到并更新視圖。
- @Watch:在某一可被應用監測的狀態發生修改的時候,執行某個額外的動作。
- AppStorage:
- 應用程序中的單例對象,由UI框架在應用程序啟動時創建,在應用程序退出時銷毀,為應用程序范圍內的可變狀態屬性提供中央存儲,簡單來說就類似于vuex/redux。
- 上述幾個狀態管理的修飾器,更多的是在同一個page中去使用,根據業務/頁面邏輯劃分組件,實現狀態管理,父子組件傳值,跨組件傳值等。
- 而AppStorage是在多頁面(page文件夾下有多個@Enter定義頁面)應用程序中用于跨頁面共享數據。
- 建議AppStorage的使用在有@Enter的組件中使用,其中的數據在組件樹中從頂部注入,對子組件來說只是一個父組件傳遞過來的狀態,保證子組件的職能單一,輸入輸出穩定,與外部數據解耦,保證復用性。
夢開始的地方(Typescript而非anyscript)
本文主要是對于復雜數據類型class的使用解讀,對于number/boolean/string暫不做解讀,請自行嘗試。
一切都是從class開始的:@State定義中明確表示只能class、number、boolean、string 及其組成的數組,并不允許object和any,所以對于復雜數據類型的定義就需要用到class,如下圖:
定義接口:
使用接口定義復雜數據(此處例子可以看出,用**new Month( )或者直接{ }**都是可以的)。
這里引用了官方文檔https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ts-rending-control-syntax-foreach-0000001149978669中的例子,根據本文檔中的例子可以看出,使用class可以定義復雜數據類型,并且其中Month8的屬性在任何地方改變都可以被observe到,calendar中使用數組方法改變數組也能被observe到,并且觸發重渲染。
非常不推薦使用**any[ ]**的方式來定義復雜數據,這樣定義的數據不會被應用observe到,數組發生改變,不會引發視圖更新!
使用class定義的數據可以使用@Props和@Link向下傳遞數據,如下圖,在second組件中修改calendar是生效的。
- 將class定義的數據傳遞給子組件。
- 子組件雙向綁定改變狀態!
跨組件傳值(@Consume和@Provide)
類似于react中的context上下文實現跨組件傳值,上層組件的狀態可以直接傳給最下層組件,非常好用。
我們已經有了@Props和@Link解決了簡單的父子組件傳值,文檔同樣提供了跨組件傳值的方法,@Provide可以直接替換掉@State定義狀態,@consume可以在需要接收的子組件中拿到傳遞下來的狀態。
定義狀態:
使用并渲染,并嘗試改變,(其實傳給下一層還是下下層使用和效果上沒啥區別)。
當然傳給第三層也可以看一下效果:
渲染結果:
在子組件中修改數組。
在子組件中修改對象中的屬性。
在子組件中修改數組中的對象的屬性(此方法失敗,狀態改變了,但是并沒有渲染,這是有問題的),正確方法見下文。
神奇的@Observed和@ObjectLink
@Observed是用來修飾類的,能夠幫忙監測多層數據中的數據變化,官方文檔中已經給出了具體的使用方法,而且非常靈活,這一對修飾器主要解決的正是上述遺留問題,如何修改數組中的對象中的屬性,并能夠自動觸發重渲染。
使用@Observed:
使用@ObjectLink,這里主要是驗證用provider/link傳遞到下層的數據能否被修改。
看效果:
從上述案例可以看出:使用@Observed和@ObjectLink可以實現對比較復雜的數據最內部數據的修改,使用起來相對靈活。
總結
本文主要對于使用class定義復雜數據,以及跨組件傳值、修改數據根據官方文檔進行簡單解析,對于狀態管理還包括AppStorage、持久化數據以及環境變量的驗證,將會在下一篇文章中做出詳解,希望本篇文章能夠在一定程度上幫助初學ets的開發者快速掌握其開發方式。