HarmonyOS 鸿蒙Next中状态管理V1迁移V2的相关问题

HarmonyOS 鸿蒙Next中状态管理V1迁移V2的相关问题 再V1@Component中可以使用@StorageProp来接收AppStorage.setOrCreate的数据V2应该使用哪个修饰符来代替?

4 回复

如果开发者需要实现类似于@StorageProp的效果,希望本地的修改不同步回AppStorage,而AppStorage的变化能够通知到使用@StorageProp装饰器的组件,可以参考以下示例对比。

V2:可以使用@Monitor@Local

import { common, Want } from '@kit.AbilityKit';
import { AppStorageV2 } from '@kit.ArkUI';

@ObservedV2
export class MyStorage {
  @Trace count: number = 0;
}

@Entry
@ComponentV2
struct Index {
  [@Local](/user/Local) storage: MyStorage = AppStorageV2.connect(MyStorage, 'storage', () => new MyStorage())!;
  [@Local](/user/Local) count: number = this.storage.count;
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  [@Monitor](/user/Monitor)('storage.count')
  onCountChange(mon: IMonitor) {
    console.info(`Index1 ${mon.value()?.before} to ${mon.value()?.now}`);
    this.count = this.storage.count;
  }

  build() {
    Column() {
      Text(`EntryAbility1 count: ${this.count}`)
        .fontSize(25)
        .onClick(() => {
          this.count++;
        })
      Button('change Storage Count')
        .onClick(() => {
          this.storage.count += 100;
        })
      Button('Jump to EntryAbility1').onClick(() => {
        let wantInfo: Want = {
          bundleName: 'com.example.myapplication', // 替换成AppScope/app.json5里的bundleName
          abilityName: 'EntryAbility1'
        };
        this.context.startAbility(wantInfo);
      })
    }
  }
}
import { common, Want } from '@kit.AbilityKit';
import { AppStorageV2 } from '@kit.ArkUI';

@ObservedV2
export class MyStorage {
  @Trace count: number = 0;
}

@Entry
@ComponentV2
struct Index1 {
  [@Local](/user/Local) storage: MyStorage = AppStorageV2.connect(MyStorage, 'storage', () => new MyStorage())!;
  [@Local](/user/Local) count: number = this.storage.count;
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  [@Monitor](/user/Monitor)('storage.count')
  onCountChange(mon: IMonitor) {
    console.info(`Index1 ${mon.value()?.before} to ${mon.value()?.now}`);
    this.count = this.storage.count;
  }

  build() {
    Column() {
      Text(`EntryAbility1 count: ${this.count}`)
        .fontSize(25)
        .onClick(() => {
          this.count++;
        })
      Button('change Storage Count')
        .onClick(() => {
          this.storage.count += 100;
        })
      Button('Jump to EntryAbility').onClick(() => {
        let wantInfo: Want = {
          bundleName: 'com.example.myapplication', // 替换成AppScope/app.json5里的bundleName
          abilityName: 'EntryAbility'
        };
        this.context.startAbility(wantInfo);
      })
    }
  }
}

V1:

// EntryAbility Index.ets
import { common, Want } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  [@StorageProp](/user/StorageProp)('count') count: number = 0;
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  build() {
    Column() {
      Text(`EntryAbility count: ${this.count}`)
        .fontSize(25)
        .onClick(() => {
          this.count++;
        })
      Button('change Storage Count')
        .onClick(() => {
          AppStorage.setOrCreate('count', AppStorage.get<number>('count') as number + 100);
        })
      Button('Jump to EntryAbility1').onClick(() => {
        let wantInfo: Want = {
          bundleName: 'com.example.myapplication', // 替换成AppScope/app.json5里的bundleName
          abilityName: 'EntryAbility1'
        };
        this.context.startAbility(wantInfo);
      })
    }
  }
}
// EntryAbility1 Index1.ets
import { common, Want } from '@kit.AbilityKit';

@Entry
@Component
struct Index1 {
  [@StorageProp](/user/StorageProp)('count') count: number = 0;
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  build() {
    Column() {
      Text(`EntryAbility1 count: ${this.count}`)
        .fontSize(50)
        .onClick(() => {
          this.count++;
        })
      Button('change Storage Count')
        .onClick(() => {
          AppStorage.setOrCreate('count', AppStorage.get<number>('count') as number + 100);
        })
      Button('Jump to EntryAbility').onClick(() => {
        let wantInfo: Want = {
          bundleName: 'com.example.myapplication', // 替换成AppScope/app.json5里的bundleName
          abilityName: 'EntryAbility'
        };
        this.context.startAbility(wantInfo);
      })
    }
  }
}

更多关于HarmonyOS 鸿蒙Next中状态管理V1迁移V2的相关问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


你好小伙伴,在V2的场景中,AppStorageV2.connect()是通过关键字进行映射的,初始化的时候复制给@Local装饰器绑定

// 使用connect在AppStorageV2中创建一个key为Message的对象
// 修改connect的返回值即可同步回AppStorageV2
[@Local](/user/Local) message: Message = AppStorageV2.connect<Message>(Message, () => new Message())!;

具体查看:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-appstoragev2#使用场景

鸿蒙Next状态管理从V1迁移至V2主要涉及以下变更:V2采用ArkTS声明式语法,废弃V1的@Provide@Consume装饰器,改用@State@Prop@Link等标准化装饰器进行状态管理。V2统一使用组件状态与应用状态管理方式,移除了AppStorage中的部分冗余API。迁移时需重构状态变量装饰器,并调整组件间状态传递机制。V2增强了状态监听能力和性能优化,要求使用ArkUI开发框架的规范语法实现状态响应。具体API差异需参考鸿蒙官方状态管理V2文档。

在HarmonyOS Next的Stage模型中,@StorageProp已被新的状态管理机制替代。推荐使用@LocalStorageLink@LocalStorageProp来替代原有的@StorageProp功能:

  1. 使用@LocalStorageLink修饰的变量与LocalStorage中对应属性建立双向同步
  2. 使用@LocalStorageProp修饰的变量与LocalStorage中对应属性建立单向同步

具体实现示例:

@Entry
@Component
struct MyComponent {
  [@LocalStorageLink](/user/LocalStorageLink)('keyName') myVar: string = 'default'
  // 或使用[@LocalStorageProp](/user/LocalStorageProp)实现单向同步
  // [@LocalStorageProp](/user/LocalStorageProp)('keyName') myVar: string = 'default'
}

数据设置方式:

// 在应用入口或其他地方初始化LocalStorage
let storage = new LocalStorage()
AppStorage.setOrCreate(storage)

// 设置数据
storage.set('keyName', 'value')

这种新的状态管理方式提供了更清晰的组件间数据流控制,建议根据实际同步需求选择对应的装饰器。

回到顶部