HarmonyOS鸿蒙Next中arkts页面A路由跳转页面B,传递map对象,B页面修改map,页面A的map同时变化
HarmonyOS鸿蒙Next中arkts页面A路由跳转页面B,传递map对象,B页面修改map,页面A的map同时变化
navPathStack.pushDestination 页面跳转,当页面从 A 跳转到 B 时,传递参数是 map<string, object> 时,时传递地址么?
现在发现 B 页面接收 map 参数后,添加或删除 key 处理完成,A 页面的 map 也会变化。
A 页面 :
@State mMapi:string, string> = new Map()
navPathStack.pushDestination({
name: 'DuuMessageDetailPage',
param: {
mMapi:this.mMapi
}
})
B 页面
@Builder
export function DetailPageBuilder(name: string,param: InfoParam) {
DetailPage({
mMapi:param.mMapi,
});
}
@State mMapi:Map<string, string> = new Map()
aboutToAppear(): void {
this.mMapi.delete("1")
}
请问这个传递的 map 是浅拷贝么?怎么解决这种问题?
更多关于HarmonyOS鸿蒙Next中arkts页面A路由跳转页面B,传递map对象,B页面修改map,页面A的map同时变化的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在ArkTS中,当页面A通过路由跳转到页面B并传递map对象时,如果B页面修改map,页面A的map也会同时变化,这是因为对象传递的是引用。以下是详细的解决方案:
1:深拷贝传递
// 页面A
@Component
struct PageA {
@State originalMap: Map<string, any> = new Map([
['name', '张三'],
['age', 25],
['city', '北京']
])
build() {
Column() {
Text('页面A')
.fontSize(20)
Text(`原始数据: ${JSON.stringify(Array.from(this.originalMap))}`)
.fontSize(14)
.margin(10)
Button('跳转到页面B')
.onClick(() => {
// 深拷贝map对象
const copiedMap = this.deepCopyMap(this.originalMap)
router.pushUrl({
url: 'pages/PageB',
params: {
dataMap: copiedMap
}
})
})
}
}
// 深拷贝Map对象
private deepCopyMap(map: Map<string, any>): Map<string, any> {
const newMap = new Map()
for (const [key, value] of map) {
if (typeof value === 'object' && value !== null) {
newMap.set(key, JSON.parse(JSON.stringify(value)))
} else {
newMap.set(key, value)
}
}
return newMap
}
}
2:使用状态管理
// 全局状态管理
class GlobalState {
private static instance: GlobalState
@State mapData: Map<string, any> = new Map()
static getInstance(): GlobalState {
if (!GlobalState.instance) {
GlobalState.instance = new GlobalState()
}
return GlobalState.instance
}
setMapData(map: Map<string, any>) {
this.mapData = new Map(map)
}
getMapData(): Map<string, any> {
return new Map(this.mapData)
}
}
// 页面A
@Component
struct PageA {
@State originalMap: Map<string, any> = new Map([
['name', '张三'],
['age', 25],
['city', '北京']
])
build() {
Column() {
Text('页面A')
.fontSize(20)
Text(`原始数据: ${JSON.stringify(Array.from(this.originalMap))}`)
.fontSize(14)
.margin(10)
Button('跳转到页面B')
.onClick(() => {
// 存储到全局状态
GlobalState.getInstance().setMapData(this.originalMap)
router.pushUrl({
url: 'pages/PageB'
})
})
}
}
}
// 页面B
@Component
struct PageB {
@State receivedMap: Map<string, any> = new Map()
aboutToAppear() {
// 从全局状态获取数据
this.receivedMap = GlobalState.getInstance().getMapData()
}
build() {
Column() {
Text('页面B')
.fontSize(20)
Text(`接收数据: ${JSON.stringify(Array.from(this.receivedMap))}`)
.fontSize(14)
.margin(10)
Button('修改数据')
.onClick(() => {
this.receivedMap.set('age', 30)
this.receivedMap.set('city', '上海')
})
Button('返回页面A')
.onClick(() => {
router.back()
})
}
}
}
更多关于HarmonyOS鸿蒙Next中arkts页面A路由跳转页面B,传递map对象,B页面修改map,页面A的map同时变化的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
Navigation的NavPathStack.pushDestination方法传递对象参数时,默认采用浅拷贝方式。对于Map这类堆内存存储的复杂对象,实际传递的是对象引用而非独立副本。当B页面通过this.mMap.delete(“1”)修改Map时,本质上操作的是A页面原始Map对象的内存地址,导致多页面状态意外联动。楼主试试深拷贝传递
// A页面传递前深拷贝
const clonedMap = new Map<string, string>(this.mMap);
navPathStack.pushDestination({
name: 'DuuMessageDetailPage',
param: { mMap: clonedMap }
});
// B页面接收后初始化新Map
@State mMMap: Map<string, string> = new Map();
aboutToAppear() {
this.mMap = new Map(param.mMap); // 通过构造函数创建独立实例
this.mMap.delete("1"); // 仅影响B页面实例
}
第一种方法:
可以结合appStorage一起使用
- 使用 @StorageLink + AppStorage 实现跨页面双向同步(或 @Provide/@Consume 实现组件树内同步)。
- 通过 Navigator 组件的 params 传递 Map 的引用标识(非直接传递 Map)。
- Map 需使用 API 11+ 支持的类型,并用 @Observed 装饰类(若涉及嵌套结构)
第二种方法
也可以使用V2装饰器,使用官方的全局状态管理基于StateStore的全局状态管理-声明式语法 - 华为HarmonyOS开发者
第三种 使用Emitter进行线程间通信
后面的页面emit事件,前面的页面监听页面
使用Emitter进行线程间通信-进程线程通信-Basic Services Kit(基础服务)-基础功能-系统 - 华为HarmonyOS开发者
我看楼主没有重新接收参数的方法,比如HMRouter是这样接收的
let res = HMRouterMgr.getCurrentParam() as NewWindowPageParam
楼主使用传递的方法是用组件的状态变量传递值,这样的值会被改变,页面传递参数是通过方法类来重新获取,重新赋值,不会存在楼主说的情况
可以使用如下方法去定义相关参数,可以实现多页面同步数据
@ObservedV2
@Trace
如:
@ObservedV2
export class Page1Param {
@Trace static param: string = '';
}
谁知道啊?传递路由参数的时候时复杂对象,怎么办?
标题
这是第一段内容。
这是第二段内容。
在HarmonyOS鸿蒙Next中,使用ArkTS进行页面路由跳转时,传递的Map对象是按引用传递的。当页面B修改接收到的Map对象时,由于页面A和页面B持有的是同一个Map对象的引用,页面A中的Map内容会同步变化。这种设计符合ArkTS基于TypeScript的引用类型特性,不需要特别处理对象共享问题。
在HarmonyOS Next的ArkTS中,Map对象作为参数传递时确实是引用传递(浅拷贝),因此B页面修改Map会影响A页面的原始数据。这是JavaScript/TypeScript的标准行为。
解决方案:
- 使用深拷贝传递Map:
// A页面跳转时
navPathStack.pushDestination({
name: 'DuuMessageDetailPage',
param: {
mMap: new Map(this.mMap) // 创建新Map实例
}
})
- 或者在B页面接收时创建副本:
// B页面
@State mMap: Map<string, string> = new Map(param.mMap) // 初始化时创建副本
- 对于复杂对象建议使用JSON序列化:
// A页面
navPathStack.pushDestination({
name: 'DuuMessageDetailPage',
param: {
mMap: JSON.parse(JSON.stringify(Array.from(this.mMap)))
}
})
// B页面
const mapData = new Map(JSON.parse(param.mMap))
选择哪种方式取决于你的具体使用场景和性能要求。第一种方式最简单直接。