LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内的“数据库”。应用程序可以创建多个LocalStorage实例,其支持UIAbility实例内多个页面间状态共享,可在页面内共享,也能通过GetShared接口跨页面共享。组件树的根节点(被@Entry装饰的@Component)可被分配LocalStorage实例,其所有子组件实例将自动获得访问权限。LocalStorage中的属性都是可变的,其生命周期由应用程序决定。
let storage = new LocalStorage(); storage.setOrCreate('PropA', 48); // 错误写法,编译报错 @LocalStorageProp() localStorageProp: number = 1; @LocalStorageLink() localStorageLink: number = 2; // 正确写法 @LocalStorageProp('PropA') localStorageProp: number = 1; @LocalStorageLink('PropA') localStorageLink: number = 2;
@LocalStorageProp("AA") a: number | null = null; // 推荐 @LocalStorageProp("AA") a: number = null; // 不推荐
通过创建LocalStorage实例,使用get、link、prop等接口操作属性,如:
let para: Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage( para); let propA: number | undefined = storage.get('PropA'); let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); link1.set(48); prop.set(1); link1.set(49);
借助@LocalStorageProp和@LocalStorageLink在UI组件内部获取状态变量,如:
class PropB { code: number; constructor(code: number) { this.code = code; } } let para: Record<string, number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage( para); storage.setOrCreate('PropB', new PropB(50)); @Component struct Child { @LocalStorageLink('PropA') childLinkNumber: number = 1; @LocalStorageLink('PropB') childLinkObject: PropB = new PropB(0); build() { Column() { Button(`Child from LocalStorage ${this.childLinkNumber}`).onClick(() => {this.childLinkNumber += 1;}) Button(`Child from LocalStorage ${this.childLinkObject.code}`).onClick(() => {this.childLinkObject.code += 1;}) } } } @Entry(storage) @Component struct CompA { @LocalStorageLink('PropA') parentLinkNumber: number = 1; @LocalStorageLink('PropB') parentLinkObject: PropB = new PropB(0); build() { Column({ space: 15 }) { Button(`Parent from LocalStorage ${this.parentLinkNumber}`).onClick(() => {this.parentLinkNumber += 1;}) Button(`Parent from LocalStorage ${this.parentLinkObject.code}`).onClick(() => {this.parentLinkObject.code += 1;}) Child() } } }
在CompA组件和Child组件中创建与storage的’PropA’单向同步数据,如:
let para: Record<string, number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage( para); @Entry(storage) @Component struct CompA { @LocalStorageProp('PropA') storageProp1: number = 1; build() { Column({ space: 15 }) { Button(`Parent from LocalStorage ${this.storageProp1}`).onClick(() => {this.storageProp1 += 1}) Child() } } } @Component struct Child { @LocalStorageProp('PropA') storageProp2: number = 2; build() { Column({ space: 15 }) { Text(`Parent from LocalStorage ${this.storageProp2}`) } } }
如:
let para: Record<string, number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage( para); let linkToPropA: SubscribedAbstractProperty<object> = storage.link('PropA'); @Entry(storage) @Component struct CompA { @LocalStorageLink('PropA') storageLink: number = 1; build() { Column() { Text(`incr @LocalStorageLink variable`).onClick(() => {this.storageLink += 1}) Text(`@LocalStorageLink: ${this.storageLink} - linkToPropA: ${linkToPropA.get()}`) } } }
通过@LocalStorageLink实现兄弟组件状态同步,如:
let ls: Record<string, number> = { 'countStorage': 1 } let storage: LocalStorage = new LocalStorage(ls); @Component struct Child { label: string = 'no name'; @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(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(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(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) } } }
在UIAbility中创建LocalStorage实例并调用windowStage.loadContent共享,在页面中通过getShared获取,如:
import { UIAbility } from '@kit.AbilityKit'; import { window } from '@kit.ArkUI'; export default class EntryAbility extends UIAbility { para:Record<string, number> = { 'PropA': 47 }; storage: LocalStorage = new LocalStorage(this.para); onWindowStageCreate(windowStage: window.WindowStage) { windowStage.loadContent('pages/Index', this.storage); } }
import { router } from '@kit.ArkUI'; let storage = LocalStorage.getShared() @Entry(storage) @Component struct Index { @LocalStorageLink('PropA') propA: number = 1; build() { Row() { Column() { Text(`${this.propA}`).fontSize(50).fontWeight(FontWeight.Bold) Button("To Page").onClick(() => { this.getUIContext().getRouter().pushUrl({ url: 'pages/Page' }) }) }.width('100%') }.height('100%') } }
import { router } from '@kit.ArkUI'; let storage = LocalStorage.getShared() @Entry(storage) @Component struct Page { @LocalStorageLink('PropA') propA: number = 2; build() { Row() { Column() { Text(`${this.propA}`).fontSize(50).fontWeight(FontWeight.Bold) Button("Change propA").onClick(() => {this.propA = 100;}) Button("Back Index").onClick(() => {this.getUIContext().getRouter().back()}) }.width('100%') } } }
let localStorage1: LocalStorage = new LocalStorage(); localStorage1.setOrCreate('PropA', 'PropA'); let localStorage2: LocalStorage = new LocalStorage(); localStorage2.setOrCreate('PropB', 'PropB'); @Entry(localStorage1) @Component struct Index { @LocalStorageLink('PropA') PropA: string = 'Hello World'; @State count: number = 0; build() { Row() { Column() { Text(this.PropA).fontSize(50).fontWeight(FontWeight.Bold) Child({ count: this.count }, localStorage2) }.width('100%') }.height('100%') } } @Component struct Child { @Link count: number; @LocalStorageLink('PropB') PropB: string = 'Hello World'; build() { Text(this.PropB).fontSize(50).fontWeight(FontWeight.Bold) } }
let localStorage1: LocalStorage = new LocalStorage(); localStorage1.setOrCreate('PropA', 'PropA'); let localStorage2: LocalStorage = new LocalStorage(); localStorage2.setOrCreate('PropB', 'PropB'); @Entry(localStorage1) @Component struct Index { @LocalStorageLink('PropA') PropA: string = 'Hello World'; @State count: number = 0; build() { Row() { Column() { Text(this.PropA).fontSize(50).fontWeight(FontWeight.Bold) Child(localStorage2) }.width('100%') }.height('100%') } } @Component struct Child { build() { Text("hello").fontSize(50).fontWeight(FontWeight.Bold) } }
let localStorage1: LocalStorage = new LocalStorage(); localStorage1.setOrCreate('PropA', 'PropA'); let localStorage2: LocalStorage = new LocalStorage(); localStorage2.setOrCreate('PropB', 'PropB'); @Entry(localStorage1) @Component struct Index { @LocalStorageLink('PropA') PropA: string = 'Hello World'; @State count: number = 0; build() { Row() { Column() { Text(this.PropA).fontSize(50).fontWeight(FontWeight.Bold) Child({}, localStorage2) }.width('100%') }.height('100%') } } @Component struct Child { @State count: number = 5; @LocalStorageLink('PropB') PropB: string = 'Hello World'; build() { Text(this.PropB).fontSize(50).fontWeight(FontWeight.Bold) } }
通过传递不同LocalStorage实例给自定义组件,在navigation跳转时显示对应绑定值,如:
let localStorageA: LocalStorage = new LocalStorage(); localStorageA.setOrCreate('PropA', 'PropA'); let localStorageB: LocalStorage = new LocalStorage(); localStorageB.setOrCreate('PropB', 'PropB'); let localStorageC: LocalStorage = new LocalStorage(); localStorageC.setOrCreate('PropC', 'PropC'); @Entry @Component struct MyNavigationTestStack { @Provide('pageInfo') pageInfo: NavPathStack = new NavPathStack(); @Builder PageMap(name: string) { if (name === 'pageOne') { pageOneStack({}, localStorageA) } else if (name === 'pageTwo') { pageTwoStack({}, localStorageB) } else if (name === 'pageThree') { pageThreeStack({}, localStorageC) } } build() { Column({ space: 5 }) { Navigation(this.pageInfo) { Column() { Button('Next Page', { stateEffect: true, type: ButtonType.Capsule }).width('80%').height(40).margin(20).onClick(() => { this.pageInfo.pushPath({ name: 'pageOne' }); }) } }.title('NavIndex').navDestination(this.PageMap).mode(NavigationMode.Stack).borderWidth(1) } } } @Component struct pageOneStack { @Consume('pageInfo') pageInfo: NavPathStack; @LocalStorageLink('PropA') PropA: string = 'Hello World'; build() { NavDestination() { Column() { NavigationContentMsgStack() Text(`${this.PropA}`) Button('Next Page', { stateEffect: true, type: ButtonType.Capsule }).width('80%').height(40).margin(20).onClick(() => { this.pageInfo.pushPathByName('pageTwo', null); }) }.width('100%').height('100%') }.title('pageOne').onBackPressed(() => {this.pageInfo.pop(); return true;}) } }
在鸿蒙 Next 中,页面级存储 LocalStorage 为开发者提供了一种方便的方式来管理页面级别的状态变量。通过使用 @LocalStorageProp 和 @LocalStorageLink 装饰器,开发者可以实现单向和双向的数据同步,满足不同的应用场景需求。无论是在单个页面内还是在多个页面之间,LocalStorage 都能够有效地共享状态,提高应用的开发效率和用户体验。同时,开发者需要注意 LocalStorage 的限制条件,以确保正确地使用和管理状态变量。