OpenHarmony頁面級UI狀態儲存:LocalStorage
LocalStorage是頁面級的UI狀態儲存,透過@Entry裝飾器接收的引數可以在頁面內共享同一個LocalStorage例項。LocalStorage也可以在UIAbility內,頁面間共享狀態。
本文僅介紹LocalStorage使用場景和相關的裝飾器:@LocalStorageProp和@LocalStorageLink。
說明:
LocalStorage從API version 9開始支援。
概述
LocalStorage是ArkTS為構建頁面級別狀態變數提供儲存的記憶體內“資料庫”。
● 應用程式可以建立多個LocalStorage例項,LocalStorage例項可以在頁面內共享,也可以透過GetShared介面,獲取在UIAbility裡建立的GetShared,實現跨頁面、UIAbility內共享。
● 元件樹的根節點,即被@Entry裝飾的@Component,可以被分配一個LocalStorage例項,此元件的所有子元件例項將自動獲得對該LocalStorage例項的訪問許可權。
● 被@Component裝飾的元件最多可以訪問一個LocalStorage例項和 AppStorage ,未被@Entry裝飾的元件不可被獨立分配LocalStorage例項,只能接受父元件透過@Entry傳遞來的LocalStorage例項。一個LocalStorage例項在元件樹上可以被分配給多個元件。
● LocalStorage中的所有屬性都是可變的。
應用程式決定LocalStorage物件的生命週期。當應用釋放最後一個指向LocalStorage的引用時,比如銷燬最後一個自定義元件,LocalStorage將被JS Engine垃圾回收。
LocalStorage根據與@Component裝飾的元件的同步型別不同,提供了兩個裝飾器:
● @LocalStorageProp :@LocalStorageProp裝飾的變數和與LocalStorage中給定屬性建立單向同步關係。
● @LocalStorageLink :@LocalStorageLink裝飾的變數和在@Component中建立與LocalStorage中給定屬性建立雙向同步關係。
限制條件
● LocalStorage建立後,命名屬性的型別不可更改。後續呼叫Set時必須使用相同型別的值。
● LocalStorage是頁面級儲存, GetShared 介面僅能獲取當前Stage透過 windowStage.loadContent 傳入的LocalStorage例項,否則返回undefined。例子可見 將LocalStorage例項從UIAbility共享到一個或多個檢視 。
@LocalStorageProp
在上文中已經提到,如果要建立LocalStorage和自定義元件的聯絡,需要使用@LocalStorageProp和@LocalStorageLink裝飾器。使用@LocalStorageProp(key)/@LocalStorageLink(key)裝飾元件內的變數,key標識了LocalStorage的屬性。
當自定義元件初始化的時候,@LocalStorageProp(key)/@LocalStorageLink(key)裝飾的變數會透過給定的key,繫結LocalStorage對應的屬性,完成初始化。本地初始化是必要的,因為無法保證LocalStorage一定存在給定的key(這取決於應用邏輯是否在元件初始化之前在LocalStorage例項中存入對應的屬性)。
說明:
從API version 9開始,該裝飾器支援在ArkTS卡片中使用。
@LocalStorageProp(key)是和LocalStorage中key對應的屬性建立單向資料同步,我們允許本地改變的發生,但是對於@LocalStorageProp,本地的修改永遠不會同步回LocalStorage中,相反,如果LocalStorage給定key的屬性發生改變,改變會被同步給@LocalStorageProp,並覆蓋掉本地的修改。
裝飾器使用規則說明
@LocalStorageProp變數裝飾器 |
說明 |
裝飾器引數 |
key:常量字串,必填(字串需要有引號)。 |
允許裝飾的變數型別 |
Object、class、string、number、boolean、enum型別,以及這些型別的陣列。巢狀型別的場景請參考 觀察變化和行為表現 。 型別必須被指定,建議和LocalStorage中對應屬性型別相同,否則會發生型別隱式轉換,從而導致應用行為異常。不支援any,不允許使用undefined和null。 |
同步型別 |
單向同步:從LocalStorage的對應屬性到元件的狀態變數。元件本地的修改是允許的,但是LocalStorage中給定的屬性一旦發生變化,將覆蓋本地的修改。 |
被裝飾變數的初始值 |
必須指定,如果LocalStorage例項中不存在屬性,則作為初始化預設值,並存入LocalStorage中。 |
變數的傳遞/訪問規則說明
傳遞/訪問 |
說明 |
從父節點初始化和更新 |
禁止,@LocalStorageProp不支援從父節點初始化,只能從LocalStorage中key對應的屬性初始化,如果沒有對應key的話,將使用本地預設值初始化。 |
初始化子節點 |
支援,可用於初始化@State、@Link、@Prop、@Provide。 |
是否支援元件外訪問 |
否。 |
圖1 @LocalStorageProp初始化規則圖示
觀察變化和行為表現
觀察變化
● 當裝飾的資料型別為boolean、string、number型別時,可以觀察到數值的變化。
● 當裝飾的資料型別為class或者Object時,可以觀察到賦值和屬性賦值的變化,即Object.keys(observedObject)返回的所有屬性。
● 當裝飾的物件是array時,可以觀察到陣列新增、刪除、更新陣列單元的變化。
框架行為
● 當@LocalStorageProp(key)裝飾的數值改變被觀察到時,修改不會被同步回LocalStorage對應屬性鍵值key的屬性中。
● 當前@LocalStorageProp(key)單向繫結的資料會被修改,即僅限於當前元件的私有成員變數改變,其他的繫結該key的資料不會同步改變。
● 當@LocalStorageProp(key)裝飾的資料本身是狀態變數,它的改變雖然不會同步回LocalStorage中,但是會引起所屬的自定義元件的重新渲染。
● 當LocalStorage中key對應的屬性發生改變時,會同步給所有@LocalStorageProp(key)裝飾的資料,@LocalStorageProp(key)本地的修改將被覆蓋。
@LocalStorageLink
如果我們需要將自定義元件的狀態變數的更新同步回LocalStorage,就需要用到@LocalStorageLink。
@LocalStorageLink(key)是和LocalStorage中key對應的屬性建立雙向資料同步:
1. 本地修改發生,該修改會被回LocalStorage中;
2. LocalStorage中的修改發生後,該修改會被同步到所有繫結LocalStorage對應key的屬性上,包括單向(@LocalStorageProp和透過prop建立的單向繫結變數)、雙向(@LocalStorageLink和透過link建立的雙向繫結變數)變數。
裝飾器使用規則說明
@LocalStorageLink變數裝飾器 |
說明 |
裝飾器引數 |
key:常量字串,必填(字串需要有引號)。 |
允許裝飾的變數型別 |
Object、class、string、number、boolean、enum型別,以及這些型別的陣列。巢狀型別的場景請參考 觀察變化和行為表現 。 型別必須被指定,建議和LocalStorage中對應屬性型別相同,否則會發生型別隱式轉換,從而導致應用行為異常。不支援any,不允許使用undefined和null。 |
同步型別 |
雙向同步:從LocalStorage的對應屬性到自定義元件,從自定義元件到LocalStorage對應屬性。 |
被裝飾變數的初始值 |
必須指定,如果LocalStorage例項中不存在屬性,則作為初始化預設值,並存入LocalStorage中。 |
變數的傳遞/訪問規則說明
傳遞/訪問 |
說明 |
從父節點初始化和更新 |
禁止,@LocalStorageLink不支援從父節點初始化,只能從LocalStorage中key對應的屬性初始化,如果沒有對應key的話,將使用本地預設值初始化。 |
初始化子節點 |
支援,可用於初始化@State、@Link、@Prop、@Provide。 |
是否支援元件外訪問 |
否。 |
圖2 @LocalStorageLink初始化規則圖示
觀察變化和行為表現
觀察變化
● 當裝飾的資料型別為boolean、string、number型別時,可以觀察到數值的變化。
● 當裝飾的資料型別為class或者Object時,可以觀察到賦值和屬性賦值的變化,即Object.keys(observedObject)返回的所有屬性。
● 當裝飾的物件是array時,可以觀察到陣列新增、刪除、更新陣列單元的變化。
框架行為
1. 當@LocalStorageLink(key)裝飾的數值改變被觀察到時,修改將被同步回LocalStorage對應屬性鍵值key的屬性中。
2. LocalStorage中屬性鍵值key對應的資料一旦改變,屬性鍵值key繫結的所有的資料(包括雙向@LocalStorageLink和單向@LocalStorageProp)都將同步修改;
3. 當@LocalStorageLink(key)裝飾的資料本身是狀態變數,它的改變不僅僅會同步回LocalStorage中,還會引起所屬的自定義元件的重新渲染。
使用場景
應用邏輯使用LocalStorage
let para: Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage(para); // 建立新例項並使用給定物件初始化 let propA: number | undefined = storage.get('PropA') // propA == 47 let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47 let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); // link2.get() == 47 let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); // prop.get() = 47 link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48 prop.set(1); // one-way sync: prop.get()=1; but link1.get() == link2.get() == 48 link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
從UI內部使用LocalStorage
除了應用程式邏輯使用LocalStorage,還可以藉助LocalStorage相關的兩個裝飾器@LocalStorageProp和@LocalStorageLink,在UI元件內部獲取到LocalStorage例項中儲存的狀態變數。
本示例以@LocalStorageLink為例,展示了:
● 使用建構函式建立LocalStorage例項storage;
● 使用@Entry裝飾器將storage新增到CompA頂層元件中;
● @LocalStorageLink繫結LocalStorage對給定的屬性,建立雙向資料同步。
// 建立新例項並使用給定物件初始化 let para:Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage(para); @Component struct Child { // @LocalStorageLink變數裝飾器與LocalStorage中的'PropA'屬性建立雙向繫結 @LocalStorageLink('PropA') storLink2: number = 1; build() { Button(`Child from LocalStorage ${this.storLink2}`) // 更改將同步至LocalStorage中的'PropA'以及Parent.storLink1 .onClick(() => this.storLink2 += 1) } } // 使LocalStorage可從@Component元件訪問 @Entry(storage) @Component struct CompA { // @LocalStorageLink變數裝飾器與LocalStorage中的'PropA'屬性建立雙向繫結 @LocalStorageLink('PropA') storLink1: number = 1; build() { Column({ space: 15 }) { Button(`Parent from LocalStorage ${this.storLink1}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already .onClick(() => this.storLink1 += 1) // @Component子元件自動獲得對CompA LocalStorage例項的訪問許可權。 Child() } } }
@LocalStorageProp和LocalStorage單向同步的簡單場景
在下面的示例中,CompA 元件和Child元件分別在本地建立了與storage的'PropA'對應屬性的單向同步的資料,我們可以看到:
● CompA中對this.storProp1的修改,只會在CompA中生效,並沒有同步回storage;
● Child元件中,Text繫結的storProp2 依舊顯示47。
// 建立新例項並使用給定物件初始化 let para:Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage(para); // 使LocalStorage可從@Component元件訪問 @Entry(storage) @Component struct CompA { // @LocalStorageProp變數裝飾器與LocalStorage中的'PropA'屬性建立單向繫結 @LocalStorageProp('PropA') storProp1: number = 1; build() { Column({ space: 15 }) { // 點選後從47開始加1,只改變當前元件顯示的storProp1,不會同步到LocalStorage中 Button(`Parent from LocalStorage ${this.storProp1}`) .onClick(() => this.storProp1 += 1) Child() } } } @Component struct Child { // @LocalStorageProp變數裝飾器與LocalStorage中的'PropA'屬性建立單向繫結 @LocalStorageProp('PropA') storProp2: number = 2; build() { Column({ space: 15 }) { // 當CompA改變時,當前storProp2不會改變,顯示47 Text(`Parent from LocalStorage ${this.storProp2}`) } } }
@LocalStorageLink和LocalStorage雙向同步的簡單場景
下面的示例展示了@LocalStorageLink裝飾的資料和LocalStorage雙向同步的場景:
// 構造LocalStorage例項 let para:Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage(para); // 呼叫link9+介面構造'PropA'的雙向同步資料,linkToPropA 是全域性變數 let linkToPropA: SubscribedAbstractProperty<object> = storage.link('PropA'); @Entry(storage) @Component struct CompA { // @LocalStorageLink('PropA')在CompA自定義元件中建立'PropA'的雙向同步資料,初始值為47,因為在構造LocalStorage已經給“PropA”設定47 @LocalStorageLink('PropA') storLink: number = 1; build() { Column() { Text(`incr @LocalStorageLink variable`) // 點選“incr @LocalStorageLink variable”,this.storLink加1,改變同步回storage,全域性變數linkToPropA也會同步改變 .onClick(() => this.storLink += 1) // 並不建議在元件內使用全域性變數linkToPropA.get(),因為可能會有生命週期不同引起的錯誤。 Text(`@LocalStorageLink: ${this.storLink} - linkToPropA: ${linkToPropA.get()}`) } } }
兄弟元件之間同步狀態變數
下面的示例展示了透過@LocalStorageLink雙向同步兄弟元件之間的狀態。
先看Parent自定義元件中發生的變化:
1. 點選“playCount ${this.playCount} dec by 1”,this.playCount減1,修改同步回LocalStorage中,Child元件中的playCountLink繫結的元件會同步重新整理;
2. 點選“countStorage ${this.playCount} incr by 1”,呼叫LocalStorage的set介面,更新LocalStorage中“countStorage”對應的屬性,Child元件中的playCountLink繫結的元件會同步重新整理;
3. Text元件“playCount in LocalStorage for debug ${storage.get<number>('countStorage')}”沒有同步重新整理,因為storage.get<number>('countStorage')返回的是常規變數,常規變數的更新並不會引起Text元件的重新渲染。
Child自定義元件中的變化:
1. playCountLink的重新整理會同步回LocalStorage,並且引起兄弟元件和父元件相應的重新整理。
let ls:Record<string,number> = { 'countStorage': 1} let storage:LocalStorage = new LocalStorage(ls); @Component struct Child { // 子元件例項的名字 label: string = 'no name'; // 和LocalStorage中“countStorage”的雙向繫結資料 @LocalStorageLink('countStorage') playCountLink: number = 0; build() { Row() { Text(this.label) .width(50).height(60).fontSize(12) Text(`playCountLink ${this.playCountLink}: inc by 1`) .onClick(() => { this.playCountLink += 1; }) .width(200).height(60).fontSize(12) }.width(300).height(60) } } @Entry(storage) @Component struct Parent { @LocalStorageLink('countStorage') playCount: number = 0; build() { Column() { Row() { Text('Parent') .width(50).height(60).fontSize(12) Text(`playCount ${this.playCount} dec by 1`) .onClick(() => { this.playCount -= 1; }) .width(250).height(60).fontSize(12) }.width(300).height(60) Row() { Text('LocalStorage') .width(50).height(60).fontSize(12) Text(`countStorage ${this.playCount} incr by 1`) .onClick(() => { storage.set<number|undefined>('countStorage', Number(storage.get<number>('countStorage')) + 1); }) .width(250).height(60).fontSize(12) }.width(300).height(60) Child({ label: 'ChildA' }) Child({ label: 'ChildB' }) Text(`playCount in LocalStorage for debug ${storage.get<number>('countStorage')}`) .width(300).height(60).fontSize(12) } } }
將LocalStorage例項從UIAbility共享到一個或多個檢視
上面的例項中,LocalStorage的例項僅僅在一個@Entry裝飾的元件和其所屬的子元件(一個頁面)中-共享,如果希望其在多個檢視中-共享,可以在所屬UIAbility中建立LocalStorage例項,並呼叫windowStage. loadContent 。
// EntryAbility.ts import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; let para:Record<string,number> = { 'PropA': 47 }; let localStorage: LocalStorage = new LocalStorage(para); export default class EntryAbility extends UIAbility { storage: LocalStorage = localStorage onWindowStageCreate(windowStage: window.WindowStage) { windowStage.loadContent('pages/Index', this.storage); } }
在UI頁面透過getShared介面獲取在透過loadContent共享的LocalStorage例項。
// 透過getShared介面獲取stage共享的LocalStorage例項 let storage = LocalStorage.getShared() @Entry(storage) @Component struct CompA { // can access LocalStorage instance using // @LocalStorageLink/Prop decorated variables @LocalStorageLink('PropA') varA: number = 1; build() { Column() { Text(`${this.varA}`).fontSize(50) } } }
說明:
對於開發者更建議使用這個方式來構建LocalStorage的例項,並且在建立LocalStorage例項的時候就寫入預設值,因為預設值可以作為執行異常的備份,也可以用作頁面的單元測試。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011554/viewspace-2989448/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS UI狀態儲存和恢復(三)iOSUI
- 本地儲存localStorage使用
- nginx狀態資訊頁面Nginx
- 使用history儲存列表頁ajax請求的狀態
- jQuery 操作checkbox翻頁儲存選中狀態jQuery
- web本地儲存(localStorage、sessionStorage)WebSession
- 將動態aspx頁面,儲存為靜態htm檔案 (轉)
- JavaScript使用localStorage儲存資料JavaScript
- localStorage設定儲存時間
- js—localstorage (本地儲存)必知JS
- localStorage和sessionStorage儲存封裝Session封裝
- canvas 儲存與還原狀態Canvas
- 【SQL Server2005頁面儲存4之--非聚集索引行在葉級別儲存】SQLServer索引
- 前端儲存除了 localStorage 還有啥前端
- Jquery 離開頁面時提示儲存jQuery
- 【SQL Server2005頁面儲存5之--非聚集索引行在非葉級別儲存】SQLServer索引
- Azure Terraform(四)狀態檔案儲存ORM
- Android 元件系列-----Activity儲存狀態Android元件
- BOM_資料儲存Cookie& localStorageCookie
- 在vue中,localStorage本地儲存應用。Vue
- HTML5本地儲存LocalstorageHTML
- 前端 | Vue 路由返回恢復頁面狀態前端Vue路由
- Android 頁面多狀態佈局管理Android
- 利用Dectorator分模組儲存Vuex狀態(下)Vue
- 利用Dectorator分模組儲存Vuex狀態(上)Vue
- Android中正確儲存view的狀態AndroidView
- vue從其他頁面返回保持上一頁的狀態Vue
- 自動儲存、靜態儲存和動態儲存
- Vue 頁面狀態保持頁面間資料傳輸的一種方法Vue
- 使用NAS動態儲存卷建立有狀態應用
- 分散式儲存Ceph之PG狀態詳解分散式
- 19c pdb如何儲存啟動狀態
- H5本地儲存:sessionStorage和localStorageH5Session
- store.js - 輕鬆實現本地儲存(LocalStorage)JS
- web頁面中http返回的狀態碼解釋WebHTTP
- redux,一種頁面狀態管理的優雅方案Redux
- 系統狀態列和app頁面一體化APP
- Linux企業級專案實踐之網路爬蟲(17)——儲存頁面Linux爬蟲