HarmonyOS 鸿蒙Next中页面间的数据共享
HarmonyOS 鸿蒙Next中页面间的数据共享 问题是:在A中点击按钮切换B、C页面时,在这两个切换的页面中,有一个共用组件D,组件D里面有个值,想要实现,D组件这个值,在B、C页面切换的过程中,能保持同步,有什么好的办法实现吗?
我试过,给切换按钮的布尔值加一个watch,每次改变,就让num重新赋值,但是不中!
代码如下:
这是主页面A:
import { HMRouter } from "@hadss/hmrouter"
import { ComB } from "./ComB"
import { ComC } from "./ComC"
@HMRouter({ pageUrl: 'ComA' })
@Component
export struct ComA {
@State isChange: boolean = false
build() {
Column() {
Button('切换按钮').onClick(() => {
this.isChange = !this.isChange
})
if (this.isChange) {
ComB()
} else {
ComC()
}
}
}
}
子页面B:
import { ComD } from "./ComD"
@Component
export struct ComB {
build() {
Column() {
Text('页面B')
ComD()
}.width('100%').height(200).backgroundColor('#857')
}
}
子页面C
import { ComD } from "./ComD"
@Component
export struct ComC {
build() {
Column() {
Text('页面C')
ComD()
}.width('100%').height(100).backgroundColor('#c0c0c0')
}
}
子页面B和子页面C的公共组件D
其中加了一个页面展示的监听,每次这个D组件展示的时候,就重新给num赋值为1
问题就是,在切换B、C页面时,这个num就会等于0,并不会维持之前的值,因为刚进入页面的时候,num被赋值为1,在切换之后,num就等于0了。
有一个解决的办法,但是我觉得不完美,其实这个赋值的位置是一个方法,这个方法会返回一个number,再重新赋值,现在的解决办法,就是定义这个num的时候,默认值不给0,直接写这个方法名字,就可以实现公共组件D中的num值保持同步。
import { HMLifecycleState, HMPopInfo, HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@Component
export struct ComD {
@State num: number = 0
aboutToAppear(): void {
HMRouterMgr.getCurrentLifecycleOwner()?.addObserver(HMLifecycleState.onShown, (ctx) => {
this.num = 1
})
}
build() {
Column() {
Text(`页面D${this.num}`)
}
}
}
更多关于HarmonyOS 鸿蒙Next中页面间的数据共享的实战教程也可以访问 https://www.itying.com/category-93-b0.html
可以再试下以下两种方式:
方式一:通过[@Link装饰器](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link#概述)实现父子组件双向同步
@HMRouter({ pageUrl: 'ComA' })
@Component
export struct ComA {
@State isChange: boolean = false
@State num: number = 0
build() {
Column() {
Button('切换按钮').onClick(() => {
this.isChange = !this.isChange
})
if (this.isChange) {
ComB({
num: $num
})
} else {
ComC({
num: $num
})
}
}
}
}
@Component
export struct ComB {
[@Link](/user/Link) num:number;
build() {
Column() {
Text('页面B')
ComD({
num:$num
})
}
.width('100%')
.height(200)
.backgroundColor('#857')
}
}
@Component
export struct ComD {
[@Link](/user/Link) num: number;
build() {
Column() {
Text(`页面D${this.num}`)
.onClick(() => {
let tmp:number = this.num + 1;
this.num = tmp
})
}
}
}
方式二:单例类实现数据共享
@ObservedV2
export class GetNum{
private static instance:GetNum;
@Trace
private num:number = 0;
private constructor() {
}
public static getInstance(){
if (!GetNum.instance) {
GetNum.instance = new GetNum();
}
return GetNum.instance
}
public getNum():number{
return this.num;
}
public setNum(num: number) {
this.num = num;
}
}
@Component
export struct ComD {
num: GetNum = GetNum.getInstance()
build() {
Column() {
Text(`页面D${this.num.getNum()}`)
.onClick(() => {
let tmp: number = this.num.getNum() + 1;
this.num.setNum(tmp)
})
}
}
}
更多关于HarmonyOS 鸿蒙Next中页面间的数据共享的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
感谢感谢!明白了!通透!!!一下想通了!,
可以通过AppStorage实现页面间的数据同步,
对于不同页面之间的参数传递,可以使用AppStorage实现。AppStorage是应用全局的UI状态存储,与应用的进程绑定,由UI框架在应用程序启动时创建。使用SubscribedAbstractProperty可以读取、设置从AppStorage/LocalStorage同步属性的数据。
如:
@Component
export struct ComD {
@State num: SubscribedAbstractProperty<number> = AppStorage.link('ComDNum');
build() {
Column() {
Text(`页面D${this.num.get()}`)
.onClick(() => {
let num: number = this.num.get() + 1
this.num.set(num)
})
}
}
}
谢谢,这也是个办法~想看看有没有更好的解决办法~,
更好的方式?你是想要什么样的实现?
1.可以通过AppStorage实现数据同步
2.为共用组件D创建一个静态的控制器,全局唯一来实现控制,对组件的操作都通过控制器来操作,数据传递也通过控制器来处理
MVVM模式-状态管理(V1)-学习UI范式状态管理-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者
可以的可以的!!!感谢~,
在HarmonyOS Next中,页面间数据共享主要通过UIAbility的AppStorage、LocalStorage和PersistentStorage实现。AppStorage提供全局内存数据共享,LocalStorage用于页面级数据共享,PersistentStorage支持持久化存储。此外,使用EventHub进行基于订阅发布机制的事件通信,也可实现跨页面数据传递。
在HarmonyOS Next中,要实现B、C页面间共用组件D的数据同步,你当前的方法确实存在问题。组件D在每次页面切换时都会重新创建,导致状态重置。以下是几种更合适的解决方案:
1. 使用AppStorage(推荐)
这是跨组件/页面共享数据的最佳方式:
// 在公共模块或组件初始化时设置初始值
AppStorage.SetOrCreate<number>('sharedNum', 0);
// 组件D中使用
@Component
export struct ComD {
@StorageLink('sharedNum') num: number = 0;
build() {
Column() {
Text(`页面D${this.num}`)
Button('增加').onClick(() => {
this.num += 1; // 修改会自动同步到所有使用该StorageLink的地方
})
}
}
}
2. 使用LocalStorage
如果共享范围仅限于特定页面树:
// 在页面A中创建并传递LocalStorage
@HMRouter({ pageUrl: 'ComA' })
@Component
export struct ComA {
@State isChange: boolean = false
storage: LocalStorage = new LocalStorage();
aboutToAppear() {
this.storage.setOrCreate('sharedNum', 0);
}
build() {
Column() {
Button('切换按钮').onClick(() => {
this.isChange = !this.isChange;
})
if (this.isChange) {
ComB({ storage: this.storage })
} else {
ComC({ storage: this.storage })
}
}
}
}
// 组件D中使用
@Component
export struct ComD {
@LocalStorageLink('sharedNum') num: number = 0;
build() {
Column() {
Text(`页面D${this.num}`)
}
}
}
3. 使用单例模式管理状态
创建全局状态管理器:
// SharedStateManager.ts
export class SharedStateManager {
private static instance: SharedStateManager;
private _num: number = 0;
private constructor() {}
static getInstance(): SharedStateManager {
if (!SharedStateManager.instance) {
SharedStateManager.instance = new SharedStateManager();
}
return SharedStateManager.instance;
}
get num(): number {
return this._num;
}
set num(value: number) {
this._num = value;
}
}
// 组件D中使用
@Component
export struct ComD {
private sharedState = SharedStateManager.getInstance();
@State num: number = this.sharedState.num;
build() {
Column() {
Text(`页面D${this.num}`)
Button('修改').onClick(() => {
this.sharedState.num = 5;
this.num = this.sharedState.num;
})
}
}
}
问题分析
你当前代码的问题在于:
- 每次切换B/C页面时,组件D都会重新实例化
aboutToAppear中的监听器在每次组件创建时都会设置num=1,但切换时组件销毁重建,状态丢失- 使用
@State装饰的状态是组件实例私有的
推荐使用AppStorage方案,它专为跨组件状态共享设计,无需复杂的生命周期管理,数据修改会自动同步到所有相关组件。

