OpenHarmony應(yīng)用ArkUI 狀態(tài)管理開發(fā)范例
本文根據(jù)橘子購物應(yīng)用,實現(xiàn)ArkUI中的狀態(tài)管理。
在聲明式UI編程框架中,UI是程序狀態(tài)的運行結(jié)果,用戶構(gòu)建了一個UI模型,其中應(yīng)用的運行時的狀態(tài)是參數(shù)。當(dāng)參數(shù)改變時,UI作為返回結(jié)果,也將進行對應(yīng)的改變。這些運行時的狀態(tài)變化所帶來的UI的重新渲染,在ArkUI中統(tǒng)稱為狀態(tài)管理機制。
自定義組件擁有變量,變量必須被裝飾器裝飾才可以成為狀態(tài)變量,狀態(tài)變量的改變會引起UI的渲染刷新。如果不使用狀態(tài)變量,UI只能在初始化時渲染,后續(xù)將不會再刷新。 下圖展示了State和View(UI)之間的關(guān)系。
#2023盲盒+碼# OpenHarmony應(yīng)用ArkUI 狀態(tài)管理開發(fā)范例-開源基礎(chǔ)軟件社區(qū)
管理組件擁有的狀態(tài)
@State裝飾器:組件內(nèi)狀態(tài)
@State裝飾的變量,或稱為狀態(tài)變量,一旦變量擁有了狀態(tài)屬性,就和自定義組件的渲染綁定起來。當(dāng)狀態(tài)改變時,UI會發(fā)生對應(yīng)的渲染改變。
在狀態(tài)變量相關(guān)裝飾器中,@State是最基礎(chǔ)的,使變量擁有狀態(tài)屬性的裝飾器,它也是大部分狀態(tài)變量的數(shù)據(jù)源。
@link裝飾器:父子雙向同步
子組件中被@Link裝飾的變量與其父組件中對應(yīng)的數(shù)據(jù)源建立雙向數(shù)據(jù)綁定。
@Link裝飾的變量與其父組件中的數(shù)據(jù)源共享相同的值。
@Component
export struct DetailPage {
@State currentLocation: string = ''
}
在父組件DetailPage中聲明當(dāng)前定位currentLocation變量。
Panel(this.isPanel) {
Location({ isPanel: $isPanel, currentLocation: $currentLocation })
}
將currentLocation變量傳給子組件Location。
@Component
export struct Location {
@Link currentLocation: string
}
子組件用@Link裝飾的currentLocation接收。
@Builder cityList(city: any) {
if (this.currentLocation === city.name) {
List() {
ForEach(city.city, twoCity => {
ListItem() {
Column() {
Text(`${twoCity}`)
.width('100%')
.height(30)
.fontSize(14)
.onClick(() => {
this.currentLocation = city.name + '/' + twoCity
})
}
}
})
}
.width('100%')
.divider({ strokeWidth: 2, color: $r('app.color.divider'), startMargin: 0, endMargin: 20 })
}
}
子組件中的currentLocation變量改變會同步父組件中的currentLocation。
管理應(yīng)用擁有的狀態(tài)
AppStorage是應(yīng)用全局的UI狀態(tài)存儲,是和應(yīng)用的進程綁定的,由UI框架在應(yīng)用程序啟動時創(chuàng)建,為應(yīng)用程序UI狀態(tài)屬性提供中央存儲。
和LocalStorage不同的是,LocalStorage是頁面級的,通常應(yīng)用于頁面內(nèi)的數(shù)據(jù)共享。而對于AppStorage,是應(yīng)用級的全局狀態(tài)共享。AppStorage使用場景和相關(guān)的裝飾器:@StorageProp和@StorageLink。
@StorageProp
@StorageProp(key)是和AppStorage中key對應(yīng)的屬性建立單向數(shù)據(jù)同步,我們允許本地改變的發(fā)生,但是對于@StorageProp,本地的修改永遠(yuǎn)不會同步回AppStorage中,相反,如果AppStorage給定key的屬性發(fā)生改變,改變會被同步給@StorageProp,并覆蓋掉本地的修改。
@Entry
@Component
struct HomePage {
@State curBp: string = 'md' // curBp指當(dāng)前窗口斷點,sm代表小屏,md代表中屏,lg代表大屏
}
在Home.ets頁面中,用@State聲明當(dāng)前窗口類型:curBp變量并賦初值為md,代表中屏。
isBreakpointSM = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'sm'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}
isBreakpointMD = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'md'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}
isBreakpointLG = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'lg'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}
根據(jù)屏幕尺寸,將curBp設(shè)置為相應(yīng)的值,并用SetOrCreate()方法保存在AppStorage中。
在子組件NavigationHomePage中直接使用curBp變量。
@Entry
@Component
export struct NavigationHomePage {
@StorageProp('curBp') curBp: string = 'sm'
}
curBp是根據(jù)窗口的尺寸判斷的,是不能改變的,因此使用@StorageProp(‘curBp’)與AppStorage(‘curBp’)建立單向數(shù)據(jù)同步。
@StorageLink
@StorageLink(key)是和AppStorage中key對應(yīng)的屬性建立雙向數(shù)據(jù)同步:
本地修改發(fā)生,該修改會被同步回AppStorage中。
AppStorage中的修改發(fā)生后,該修改會被同步到所有綁定AppStorage對應(yīng)key的屬性上,包括單向(@StorageProp和通過Prop創(chuàng)建的單向綁定變量)、雙向(@StorageLink和通過Link創(chuàng)建的雙向綁定變量)變量和其他實例(比如PersistentStorage)。
@Entry
@Component
struct HomePage {
@StorageLink('shoppingCartGoodsList') shoppingCartGoodsList: { data: { id: number } }[] = []
}
在Home.ets頁面中,用@StorageLink裝飾器定義shoppingCartGoodsList,用于獲取全局的購物車商品列表。
this.emitterClass.setShoppingCartGoodsList((eventData)=>{
this.shoppingCartGoodsList.push(eventData.data.id)
AppStorage.SetOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList)
})
使用AppStorage.SetOrCreate(‘shoppingCartGoodsList’, this.shoppingCartGoodsList)將購物車商品列表保存在AppStorage中。
因為購物車中的商品會聯(lián)動的變化,比如在商品的詳情頁將商品添加至購物車,在首頁也需要更新購物車信息,因此購物車商品列表采用@StorageLink裝飾器裝飾,與AppStorage(‘shoppingCartGoodsList’)建立雙向同步。
運行測試效果
執(zhí)行以下命令,可以下載橘子購物應(yīng)用工程:
git init
git config core.sparsecheckout true
echo code/Solutions/Shopping/OrangeShopping/ > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master