目录
LocalStorage页面存储
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
存储的数据
import { StorageChildren } from "../view/StorageChildren"
// 实例化一个对象,并设置了存储数据
let para:Record<string,number> = {'username':100}
let stor:LocalStorage = new LocalStorage(para)
@Entry
@Component
方式二、创建LocalStorage
实例,通过实例方法来初始化storage
存储的数据
import { StorageChildren } from "../view/StorageChildren"
// 实例化一个对象,并设置了存储数据
let storage:LocalStorage = new LocalStorage("UserName")
storage.setOrCreate('UserName',"小王")
@Entry
@Component
struct Page13_Storage {
第二步、绑定Storage
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
:可以从页面级别存储中获取数据或者修改数据。
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%")
}
}
第四步、修改数据的过程
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
来实现数据的获取以及双向更新。父节点可以同步更新数据。
@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
文件:
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
共享
// 通过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
定义一个全局存储
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
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
:
// 通过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对象,绑定到页面中
let storage = LocalStorage.getShared()
@Entry(storage)
这样就可以在页面中通过prop
装饰器来实现共享。如下效果,多个页面共享一个状态
注意事项:这个功能演示无法在预览器实现,必须要模拟器或者真机来实现,我们需要用到全局windo
窗口Ability
。
AppStorage应用存储
AppStorage前言
应用存储那就意味着项目中任何页面都可以实现共享,不需要借助Abilitry
来实现,类似于状态机,只要状态机有数据,页面就直接可以获取出来。
AppStorage使用格式
页面1
@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
只能实现获取数据,无法修改全局的数据。
@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%')
}
}
效果: