LocalStorage 前言
LocalStorage 是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例多个页面间状态共享。 可以直接理解为LocalStorage就是内存数据库,你可以往里面存放数据,LocalStorage和AppStorage都是内存级别的存储方案。唯一不同的在于作用范围。
LocalStorage 解决问题及特性
- 在同一个
EneryAlibity中多个页面可以实现数据共享,不同EneryAlibity无法实现数据共享。- LocalStorage可以实现一个页面中定义了存储的数据,在他的子组件中都可以共享给这个内存的数据。
- 应用程序可以创建多个
LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过getShared接口,实现跨页面、UIAbility实例内共享。- 组件树的根节点,即被
@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。@Component装饰的组件既可以自动继承来自父组件的LocalStorage实例,也可以传入指定的LocalStorage的实例,详见:自定义组件接收LocalStorage实例。LocalStorage中的所有属性都是可变的。
LocalStorage代码的实现步骤:
第一步、创建初始化storage
方式一、先创建一个LocalStorage实例,通过构造函数初始化storage存储的数据
|
1 2 3 4 5 6 7 8 |
import { StorageChildren } from "../view/StorageChildren" // 实例化一个对象,并设置了存储数据 let para:Record<string,number> = {'username':100} let stor:LocalStorage = new LocalStorage(para) @Entry @Component |
方式二、创建LocalStorage实例,通过实例方法来初始化storage存储的数据
|
1 2 3 4 5 6 7 8 9 |
import { StorageChildren } from "../view/StorageChildren" // 实例化一个对象,并设置了存储数据 let storage:LocalStorage = new LocalStorage("UserName") storage.setOrCreate('UserName',"小王") @Entry @Component struct Page13_Storage { |
第二步、绑定Storage
|
1 2 3 4 5 6 7 8 9 |
import { StorageChildren } from "../view/StorageChildren" // 实例化一个对象,并设置了存储数据 let storage:LocalStorage = new LocalStorage("UserName") storage.setOrCreate('UserName',"小王") @Entry(storage) @Component struct Page13_Storage { |
需要将Storage实例绑定给对应的entry装饰的组件,这样才能表达当前这个页面具有指定某一个storage内存状态,以后这个页面所有子组件都可以共享这一个storage对象。
第三步、获取storage数据
一、@LocalStorageProp:代表可以从页面级存储中获取数据。 二、@LocalStorageLink:可以从页面级别存储中获取数据或者修改数据。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import { StorageChildren } from "../view/StorageChildren" // 实例化一个对象,并设置了存储数据 let storage:LocalStorage = new LocalStorage("userName") storage.setOrCreate('userName',"小王") @Entry(storage) @Component struct Page13_Storage { @State message: string = 'Page13_Storage'; // 表达从内存中获取页面级别存储,如果获取不到给本地userName初始化值 @LocalStorageProp("userName") username:string = "默认值" build() { Column(){ Text(this.message).fontSize(30).fontColor(Color.Red) Text(this.username).fontSize(26) StorageChildren() }.width("100%") .height("100%") } } |
第四步、修改数据的过程
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import { StorageChildren } from "../view/StorageChildren" // 实例化一个对象,并设置了存储数据 let storage:LocalStorage = new LocalStorage("userName") storage.setOrCreate('userName',"小王") @Entry(storage) @Component struct Page13_Storage { @State message: string = 'Page13_Storage'; // 表达从内存中获取页面级别存储,如果获取不到给本地userName初始化值 @LocalStorageProp("userName") username:string = "默认值" @LocalStorageLink("userName") myUserName:string = "默认值2" build() { Column(){ Text(this.message).fontSize(30).fontColor(Color.Red) Text(this.username).fontSize(26).onClick(()=>{ // 本地userName改了,没有影响存储中的userName this.username = "WuYouke" }) Text(this.myUserName).fontSize(26).fontColor(Color.Orange).onClick(()=>{ // 本地userName没有修改,修改的是页面存储的userName this.myUserName = "WuQi" }) StorageChildren() }.width("100%") .height("100%") } } |
LocalStorageProp中本地userName修改了,但是没有影响页面中存储的userName,而LocalStorageLink修改了页面存储的userName却没有修改本地存储的userName
第五步、子组件获取数据
StorageChildren页面:子节点可以通过link来实现数据的获取以及双向更新。父节点可以同步更新数据。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@Component export struct StorageChildren{ @LocalStorageProp("userName") username:string = "默认值" @LocalStorageLink("userName") myUserName:string = "默认值2" build() { Column(){ Text("StorageChildren:").fontSize(20) Text(`${this.username}`) .fontSize(16) .fontColor(Color.Blue) .onClick(()=>{ this.username = "张三李四" }) Text(`${this.myUserName}`) .fontSize(16) .fontColor(Color.Brown) .onClick(()=>{ this.myUserName = "WuMan" }) }.width("100%") .height("100%") } } |
将LocalStorage共享到一个或多个视图
上面实例中,LocalStorage的实例仅仅在一个@Entry装饰的组件和其所有属性的子组件中共享,如果希望其在多个视图中共享,可以在所属的UIAbility中创建LocalStorage实例,并调用windowStage.loadContent EntryAbility.ets 文件:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
para: Record<string, string> = {'theme': 'Red'}; storage: LocalStorage = new LocalStorage(this.para); onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.loadContent('pages/Index', this.storage,(err) => { if (err.code) { hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); return; } hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); } |
首页获取UIAbility共享
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 通过getShared接口获取stage共享的LocalStorage实例 let storage = LocalStorage.getShared() @Entry(storage) @Component struct Page02_TaskList{ @LocalStorageLink("theme") theme:string = "默认值" @State tasks:Array<TaskModel> = [] aboutToAppear(): void { const tasks = CreateTaskModel.initData() this.tasks = tasks console.log("tasks",this.tasks) } @State myTitle:string = "Harmony OS" build() { RelativeContainer(){ Column(){ Text(this.theme) // Text(`${JSON.stringify(this.tasks)}`) Text("你好,小王") |
效果:
多个页面实时共享页面状态 首先在EntryAbility定义一个全局存储
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; const DOMAIN = 0x0000; export default class EntryAbility extends UIAbility { para: Record<string, string> = {'theme': 'Red'}; storage: LocalStorage = new LocalStorage(this.para); onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.loadContent('pages/Index', this.storage,(err) => { if (err.code) { hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); return; } hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); } } |
现给Abilitry设置一个页面存储对象,这样才能保证这个Abilitry下面所有子页面都可以共享这个storage
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import { router } from '@kit.ArkUI'; // 通过getShared接口获取stage共享的LocalStorage实例 let storage = LocalStorage.getShared() @Entry(storage) @Component struct Page02_TaskList{ @LocalStorageLink("theme") theme:string = "默认值" build() { RelativeContainer(){ Column(){ Text(this.theme).fontSize(30) Button("修改颜色").onClick((event: ClickEvent) => { this.theme = "Orange" }) Button("详情页面跳转").onClick((event: ClickEvent) => { router.pushUrl({ url:'pages/Detail' },router.RouterMode.Standard,(err)=>{ if(err){ console.log("路由跳转报错") } }) }) |
子页面也需要引入共享状态Detail.ets:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// 通过getShared接口获取stage共享的LocalStorage实例 let storage = LocalStorage.getShared() @Entry(storage) @Component struct Detail { @State message: string = 'Hello World'; @LocalStorageLink("theme") theme:string = "默认值" build() { Column() { Text(this.theme).fontSize(30) Button("再次修改颜色").onClick((event: ClickEvent) => { this.theme = "Pink" }) } .height('100%') .width('100%') } } |
在页面中,通过getShared拿到数据storage对象,绑定到页面中
|
1 2 |
let storage = LocalStorage.getShared() @Entry(storage) |
这样就可以在页面中通过prop装饰器来实现共享。如下效果,多个页面共享一个状态 注意事项:这个功能演示无法在预览器实现,必须要模拟器或者真机来实现,我们需要用到全局
windo窗口Ability。
AppStorage应用存储
AppStorage前言
应用存储那就意味着项目中任何页面都可以实现共享,不需要借助Abilitry来实现,类似于状态机,只要状态机有数据,页面就直接可以获取出来。
AppStorage使用格式
页面1
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Entry @Component struct Page02_TaskList{ @StorageLink('PropA') storageLink:number = 100 build() { RelativeContainer(){ Column(){ Text(`storageLink:${this.storageLink}`).fontSize(30) Button("增加").onClick((event: ClickEvent) => { this.storageLink = 200 }) Button("详情页面跳转").onClick((event: ClickEvent) => { router.pushUrl({ url:'pages/Detail' },router.RouterMode.Standard,(err)=>{ if(err){ console.log("路由跳转报错") } }) }) |
当进入项目中第一个页面发现又全局存储的对象PropA,判断全局存储里面是否又这个变量,如果有则获取这个变量的值拿到页面中使用,如果没有这个变量,将这个页面的初始化的值作为全局存储的结果。StorageLink初始化,更新,获取三个功能。
页面2
直接使用@StorageLink('PropA') storageLink:number = 0; 有的话就用,没有的话重新创建赋默认值,通过link可以实现在页面二修改全局的数据,通过prop只能实现获取数据,无法修改全局的数据。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Entry @Component struct Detail { @StorageLink('PropA') storageLink:number = 0; build() { Column() { Text(`this.storageLink:${this.storageLink}`).fontSize(30) Button("修改").onClick((event: ClickEvent) => { this.storageLink = 50 }) } .height('100%') .width('100%') } } |
效果:
链接:https://juejin.cn/post/7502769271626416168
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。