You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular父子Mat Dialog传参致对象属性被意外修改问题排查

Mat Dialog传递对象后修改子组件数据导致父组件原数据污染的问题分析

错误原因

你用{...this.scenarios[i]}或Object.assign({}, this.scenarios[i])做的是浅拷贝:

  • 浅拷贝只会复制对象的第一层基本类型属性(比如id、name这些字符串/数字),但对于ScenarioPreview里的photos数组这种引用类型,浅拷贝只会复制数组的内存引用,不会创建新的数组实例。
  • 这就导致子组件中this.scenario.photos和父组件this.scenarios[i].photos指向的是同一个数组,你在子组件中修改数组元素时,本质上是直接修改了父组件的原数据。每次打开预览都会重复添加前缀,自然就出现了叠加的问题。

解决方法

需要对包含引用类型的对象做深拷贝,确保子组件操作的是完全独立的数据副本,以下是几种可行的实现方式:

方式1:在父组件传递数据时手动深拷贝

openPreviewModel(i: number) {
  const originalScenario = this.scenarios[i];
  // 复制所有属性,并重新创建photos数组,切断引用
  const copiedScenario = {
    ...originalScenario,
    photos: [...originalScenario.photos]
  };
  this.matDialog.open(PreviewScenariosComponent, {data: copiedScenario});
}

如果要结合你的ScenarioPreview类,可以这样写:

openPreviewModel(i: number) {
  const original = this.scenarios[i];
  const copied = new ScenarioPreview({
    ...original,
    photos: [...original.photos]
  });
  this.matDialog.open(PreviewScenariosComponent, {data: copied});
}

方式2:在子组件中创建独立副本后再修改

ngOnInit(): void {
  // 先创建包含独立photos数组的副本,再进行修改
  this.scenario = {
    ...this.data,
    photos: [...this.data.photos]
  } as ScenarioPreview;
  
  for (let j = 0; j < this.scenario.photos.length; j++) {
    let base64_photo = this.scenario.photos[j];
    this.scenario.photos[j] = `data:image/png;base64,${base64_photo}`;
  }
  this.current_photo = this.scenario.photos[this.current_photo_index];
}

方式3:使用结构化克隆API(简洁版)

如果你的环境支持structuredClone(现代浏览器及Node.js 17+),可以直接用它做深拷贝:

openPreviewModel(i: number) {
  const copiedScenario = structuredClone(this.scenarios[i]);
  this.matDialog.open(PreviewScenariosComponent, {data: copiedScenario});
}

内容的提问来源于stack exchange,提问作者Brave Spirit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:52:47