LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。

概述

LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”。

  • 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,实现跨页面、UIAbility实例内共享。

  • 组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。

  • 被@Component装饰的组件最多只能访问一个LocalStorage实例和,没有被@Entry装饰的组件不会被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。

  • LocalStorage中的所有属性都是可变的。

应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时,比如销毁最后一个自定义组件,LocalStorage将被JS Engine垃圾回收。

LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:

  • @LocalStorageProp:@LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系

  • @LocalStorageLink:@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系

@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量会通过给定的key,绑定LocalStorage对应的属性,完成初始化。本地初始化是必要的,因为无法保证LocalStorage一定存在给定的key(这取决于应用逻辑是否在组件初始化之前在LocalStorage实例中存入对应的属性)

@LocalStorageProp(单向同步)

@LocalStorageProp(key)是和LocalStorage中key对应的属性建立单向数据同步,可以对key对应的值进行修改,本地的修改不会同步到LocalStorage中。

如果LocalStorage中key对应的值发生了改变,比如通过set修改,改变会同步给@LocalStorageProp(key),并会覆盖本地的值

@LocalStorageProp和LocalStorage单向同步使用

  • CompA中对this.storProp1的修改,只会在CompA内生效,并没有同步回storage:LocalStorage中;

  • Child组件中,Text绑定的storProp2 依旧显示47

// 创建新实例并使用给定对象初始化
let para: Record<string, number> = { 'PropA': 47 };
let storage: LocalStorage = new LocalStorage(para);
// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct CompA {
  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
  @LocalStorageProp('PropA') storageProp1: number = 1;

  build() {
    Column({ space: 15 }) {
      // 点击后从47开始加1,只改变当前组件显示的storageProp1,不会同步到LocalStorage中
      Button(`Parent from LocalStorage ${this.storageProp1}`)
        .onClick(() => {
          this.storageProp1 += 1
        })
      Child()
    }
  }
}

@Component
struct Child {
  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
  @LocalStorageProp('PropA') storageProp2: number = 2;

  build() {
    Column({ space: 15 }) {
      // 当CompA改变时,当前storageProp2不会改变,显示47
      Text(`Parent from LocalStorage ${this.storageProp2}`)
    }
  }
}

@LocalStorageLink和LocalStorage双向同步使用

// 构造LocalStorage实例
let para: Record<string, number> = { 'PropA': 47 };
let storage: LocalStorage = new LocalStorage(para);
// 调用link(api9以上)接口构造'PropA'的双向同步数据,linkToPropA 是全局变量
let linkToPropA: SubscribedAbstractProperty<object> = storage.link('PropA');

@Entry(storage)
@Component
struct CompA {

  // @LocalStorageLink('PropA')在CompA自定义组件中创建'PropA'的双向同步数据,初始值为47,因为在构造LocalStorage已经给“PropA”设置47
  @LocalStorageLink('PropA') storageLink: number = 1;

  build() {
    Column() {
      Text(`incr @LocalStorageLink variable`)
        // 点击“incr @LocalStorageLink variable”,this.storageLink加1,改变同步回storage,全局变量linkToPropA也会同步改变

        .onClick(() => {
          this.storageLink += 1
        })

      // 并不建议在组件内使用全局变量linkToPropA.get(),因为可能会有生命周期不同引起的错误。
      Text(`@LocalStorageLink: ${this.storageLink} - linkToPropA: ${linkToPropA.get()}`)
    }
  }
}

将LocalStorage实例从UIAbility共享到一个或多个视图

要在多个视图中共享,可以在所属UIAbility中创建LocalStorage实例,并调用windowStage.loadContent。

// EntryAbility.ts
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';

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);
}
}

注意:

在UI页面通过getShared接口获取通过loadContent共享的LocalStorage实例。

LocalStorage.getShared()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效

Index页面中的propA通过getShared()方法获取到共享的LocalStorage实例。点击Button跳转到Page页面,点击Change propA改变propA的值,back回Index页面后,页面中propA的值也同步修改

// index.ets
import router from '@ohos.router';

// 通过getShared接口获取stage共享的LocalStorage实例
let storage = LocalStorage.getShared()

@Entry(storage)
@Component
struct Index {
  // can access LocalStorage instance using 
  // @LocalStorageLink/Prop decorated variables
  @LocalStorageLink('PropA') propA: number = 1;

  build() {
    Row() {
      Column() {
        Text(`${this.propA}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button("To Page")
          .onClick(() => {
            router.pushUrl({
              url: 'pages/Page'
            })
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}
// Page.ets
import router from '@ohos.router';

let storage = LocalStorage.getShared()

@Entry(storage)
@Component
struct Page {
  @LocalStorageLink('PropA') propA: number = 2;

  build() {
    Row() {
      Column() {
        Text(`${this.propA}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)

        Button("Change propA")
          .onClick(() => {
            this.propA = 100;
          })

        Button("Back Index")
          .onClick(() => {
            router.back()
          })
      }
      .width('100%')
    }
  }
}

总结:

LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。

应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时LocalStorage将被JS Engine垃圾回收。

@Entry装饰的@Component,可以被分配一个LocalStorage实例,其下子组件自动获得对该LocalStorage实例的访问权限。

被@Component装饰的组件最多只能访问一个LocalStorage实例和AppStorage。

@LocalStorageProp(key)是和LocalStorage中key对应的属性建立单向数据同步,可以对key对应的值进行修改,本地的修改不会同步到LocalStorage中。

@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系

想要在多个视图中共享,可以在所属UIAbility中创建LocalStorage实例,并调用windowStage.loadContent。

建议使用这个方式来构建LocalStorage的实例,并且在创建LocalStorage实例的时候就写入默认值,因为默认值可以作为运行异常的备份,也可以用作页面的单元测试。

:LocalStorage.getShared()只在模拟器或者实机上才有效,在Previewer预览器中使用不生效

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐