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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。