ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

LocalStorage页面存储

LocalStorage 前言

LocalStorage 是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例多个页面间状态共享。
可以直接理解为LocalStorage就是内存数据库,你可以往里面存放数据,LocalStorageAppStorage都是内存级别的存储方案。唯一不同的在于作用范围。

LocalStorage 解决问题及特性

  1. 在同一个EneryAlibity中多个页面可以实现数据共享,不同EneryAlibity无法实现数据共享。
  2. LocalStorage可以实现一个页面中定义了存储的数据,在他的子组件中都可以共享给这个内存的数据。
  3. 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过getShared接口,实现跨页面、UIAbility实例内共享。
  4. 组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。
  5. @Component装饰的组件既可以自动继承来自父组件的LocalStorage实例,也可以传入指定的LocalStorage的实例,详见:自定义组件接收LocalStorage实例。
  6. 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%")
  }
}

ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

第四步、修改数据的过程
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%")
  }
}

效果:
ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

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%")
  }
}

ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

将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.');
    });
  }

ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用
首页获取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("你好,小王")

效果:
ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

多个页面实时共享页面状态
首先在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装饰器来实现共享。如下效果,多个页面共享一个状态
ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用
注意事项:这个功能演示无法在预览器实现,必须要模拟器或者真机来实现,我们需要用到全局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%')
  }
}

效果:
ArkTS存储机制深入解析:LocalStorage与AppStorage的高效应用

完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值