【问题标题】:Angular 10 - View doesn't update when model is modifiedAngular 10 - 修改模型时视图不会更新
【发布时间】:2021-05-21 09:21:48
【问题描述】:

Angular 10.1.6,TypeScript 4.0.5

你好

上下文

在我的 webapp 中,我有 3 个组件。

组件A存储Array<Image>

export class ComponentParentA implements OnInit {
  images: Array <Image> ;

  addImageToList(newImage: Image) {
    this.images.push(newImage)
  }
}

组件 C 显示图像列表。

export class ComponentChildC implements OnInit {

  @Input() images: Array <Image>;
}

组件 C 从组件 A 的 html 模板中调用,如下所示:

<ComponentChildC [images]="images"></ComponentChildC>

组件 B 负责联系我的 API,添加之前选择的图像。 API 返回一个 Image 对象,它对应于我的模型。组件发出图像,因此 ComponentA 将返回的图像添加到其数组中(调用 addImageToList)
addImage 是 this.http.post (HttpClient) 的 Observable 返回

export class ComponentChildB implements OnInit, AfterViewInit {
  @Output() eventCreateImage : EventEmitter<Image>;

  addImage(data) {
    this.service.addImage(data).subscribe((image) => {
        this.eventCreateImage.emit(image)
      })
  }

}

组件 A 像这样调用组件 B:

<ComponentChildB (eventCreateImage)="addImageToList($event)"></ComponentChildB>

问题

当我单击按钮时,组件 B 添加图像。此点击触发addImage 函数。所有组件都正常工作,图像保存在我的服务器上。 API返回图像,后者正确存储在组件A的Array中。但是,组件C的视图没有更新,新创建的图像也没有出现。如果我再次单击该按钮,则会存储一个新图像。这一次,我之前看不到的之前的图像正确显示了。新图像不会。

我希望图像直接出现。

我已经做过的事情

我在网上看到过类似的问题。

  • First,我试图在addImageToList 函数中用this.images = this.images.concat(newImage) 替换this.images.push(newImage)。它不起作用。
  • 接下来,我看到了,因为图像是一个数组,当我在数组中添加一个新图像时,Angular 不会检测到任何变化。我让我的组件 C 实现了 OnChange 接口。实际上,不会调用 ngOnChange 函数。
  • 我看到here 我可以尝试手动重新加载我的组件所以我让我的组件 C 实现 DoCheck。奇怪的东西出现了。当我单击按钮并在组件 C 的 ngDoCheck 中执行 console.log(this.images) 时,我看到列表已正确更新。但是图像仍然没有出现。于是我尝试调用ChangeDetectorRef markForCheck 和 detectChanges 之类的方法来通知组件发生了变化,但是没有成功。

如果你知道我的问题可能来自哪里,如果你能帮助我,我将不胜感激

【问题讨论】:

  • 你试过 this.images = this.images.concat([newImage])..or this.images = [...this.images, newImage]???
  • @lissettdm 感谢您的提议,不幸的是它没有奏效。

标签: javascript angular typescript components


【解决方案1】:

我没有测试,但我认为这是导致策略检测的原因。您可以尝试 3 种不同的解决方案(我现在无法测试,但通常它会起作用)。

PS:对不起我的英语

1/ 在您的对象中 @Component 在您的组件中添加 changeDetection

@Component({
  selector: 'app-component',
  template: `...`,
  changeDetection: ChangeDetectionStrategy.OnPush
})

然后在你的函数 addImageToList() 中替换你的代码

addImageToList(newImage) {
   this.images = [...this.images, newImage]
}

2/ 在你的组件 C 中替换你的 @Input 为

@Input() set images(value: Array <Image>) {
      myImages = value
 }

html 中的属性绑定将是 myImages 在此上下文中

3/ 您可以使用 ChangeDetectorRef 服务手动更改策略检测。在您的构造函数组件 A 中添加此服务,然后在您的函数中添加:

constructor(
     private cd: ChangeDetectorRef
   ){}

  addImageToList(newImage: Image) {
    this.images = [...this.images, newImages];
    this.cd.markForCheck();
  }

如果此解决方案不起作用,请查看 Angular 中的检测策略文档或尝试将 1 和 2 混合在一起

【讨论】:

  • 感谢您的帮助。您的提议没有奏效,但由于您的最后解决方案,我解决了我的问题。我不得不使用 detectChanges 而不是 markForCheck 但它有效:)
  • 但是,即使图像出现,它们的行为也很奇怪。在我的应用程序中,当我单击图像时,组件 A 中的属性 SelectedImage 将图像作为值。仅当此属性不为空时才会出现其他组件,但是即使此属性具有正确的值,其他组件也不会对新更改做出反应。正常吗?
猜你喜欢
  • 1970-01-01
  • 2020-03-03
  • 2014-02-01
  • 2016-08-23
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
相关资源
最近更新 更多