LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内的“数据库”。LocalStorage可以实现同一个UIAbility下页面之间以及同一页面下组件之间的数据共享与同步。
LocalStorage初始化理解(重点)
当自定义组件初始化的时候,@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量会通过给定的key,绑定LocalStorage对应的属性,完成初始化。如果LocalStorage实例对象中存在该key,则通过@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量的初始值会被忽略。
class Person {
name: string = ''
age: number = 0
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
let para: Record<string, Person> = {
'p1' : new Person('', 18)
};
let storage: LocalStorage = new LocalStorage(para);
@Entry(storage)
@Component
struct Index {
// 当storage实例中存在键值对{'p1' : new Person('', 18)}, 所以下面的初始化会被忽略
@LocalStorageLink('p1') pa: Person = new Person('小李', 20);
@State count: number = 0;
build() {
Row() {
Column() {
Text(this.pa.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.backgroundColor(Color.Gray)
}
.width('100%')
}
.height('100%')
}
}
本地初始化是必要的,因为无法保证LocalStorage一定存在给定的key。因此,如果LocalStorage实例中不存在属性,则编译器用该初始值初始化该属性,并存入LocalStorage中。下面的情况很好说明了这一点。
let storage: LocalStorage = new LocalStorage();
@Entry(storage)
@Component
struct Index {
// 由于storage实例中不存在键值对,所以编译器会用下面的初始值{'p1': {'小李', 20}}存入storage实例对象中
@LocalStorageLink('p1') pa: Person = new Person('小李', 20);
@State count: number = 0;
build() {
Row() {
Column() {
Text(this.pa.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.backgroundColor(Color.Gray)
}
.width('100%')
}
.height('100%')
}
}
此外,LocalStorage可以通过方法setOrCreate设置或修改键值对。
具体接口为:setOrCreate<T>(propName: string, newValue: T): boolean
如果propName已经在LocalStorage中存在,并且newValue和propName对应属性的值不同,则设置propName对应属性的值为newValue,否则状态变量不会通知UI刷新propName对应属性的值。
可以通过此方法为LocalStorage创建多个键值对
同一页面下组件间的数据共享与同步
使用步骤
一、使用构造函数创建LocalStorage实例对象storage
LocalStorage的构造函数接口如下:constructor(initializingProperties?: Object)。
通常使用泛型工具类Record<string, T>来构造Object类型。initializingProperties需要包含一个string类型的键用于标识LocalStorage实例以及一个指定类型的实例对象。
被@Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage,未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。
因此,实例化LocalStorage对象的代码通常写在组件外。
class Person {
name: string = ''
age: number = 0
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
let para: Record<string, Person> = {
'p1' : new Person('测试员-小王', 18)
};
let storage: LocalStorage = new LocalStorage(para);
二、用@Entry(LocalStorage实例对象名称)装饰组件
@Entry装饰的自定义组件为页面的默认入口组件,需要给入口组件通过参数传递LocalStorage实例对象的名称。
class Person {
name: string = ''
age: number = 0
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
let para: Record<string, Person> = {
'p1' : new Person('测试员-小王', 18)
};
let storage: LocalStorage = new LocalStorage(para);
@Entry(storage)
@Component
struct Index {
build() {
...
}
}
三、使用@LocalStorageProp或@LocalStorageLink装饰需要在组件间传递的变量
注意:@LocalStorageProp和@LocalStorageLink允许装饰的变量类型只有Object、class、string、number、boolean、enum类型,以及这些类型的数组。API12及以上支持Map、Set、Date类型。API12及以上支持上述支持类型的联合类型,比如string | number, string | undefined 或者 ClassA | null。
@LocalStorageProp和@LocalStorageLink都不支持从父节点初始化,只能从LocalStorage中key对应的属性初始化,如果没有对应key的话,将使用本地默认值初始化。
class Person {
name: string = ''
age: number = 0
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
let param: Record<string, Person> = {
'p1' : new Person('测试员小王', 0)
};
let storage: LocalStorage = new LocalStorage(param);
@Entry(storage)
@Component
struct Index {
@LocalStorageLink('p1') pa: Person = new Person('小李', 20);
@State count: number = 0;
build() {
Row() {
Column() {
Text(this.pa.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.backgroundColor(Color.Gray)
.onClick(() => {
this.pa.name = '测试员-小红'
})
// 使用LocalStorage 实例localStorage2
Child1({ count: this.count })
.width('100')
.backgroundColor(Color.Pink)
}
.width('100%')
}
.height('100%')
}
}
@Component
struct Child1 {
@Link count: number;
@LocalStorageLink('p1') pb: Person = new Person('小黎明', 20);
build() {
Text(this.pb.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
}
注意:未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。
同一UIAbility下页面间的数据共享与同步
方法一 将当前页面下LocalStorage实例对象导出
具体操作大致为:
// page1.ets
....
export let storage: LocalStorage = new LocalStorage(param);
....
// page2.ets
import {storage} from 'xx/page1'
方法二 通过getShared获取LocalStorage实例
具体步骤:
一、在在所属UIAbility中创建LocalStorage实例,并调用windowStage
注意需要将创建的LocalStorage实例传递给windowStage.loadContent的第二个参数。
// EntryAbility.ets
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);
}
}
LocalStorage.getShared()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效。
LocalStorage.getShared()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效。
LocalStorage.getShared()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效。
二、在需求页面通过getShared获取storage实例
// 例如index.ets需要用到storage实例
// 通过getShared接口获取stage共享的LocalStorage实例
let storage = LocalStorage.getShared()