在服务中使用 FormArray 时的 OnPush 更改检测

Posted

技术标签:

【中文标题】在服务中使用 FormArray 时的 OnPush 更改检测【英文标题】:OnPush change detection when using a FormArray in a service 【发布时间】:2021-08-04 17:30:53 【问题描述】:

各位开发者,

我有一个存储FormArray 的服务,它由一个组件附加并由另一个组件查看。即使FormArray 是不可变的并且被重新分配,视图也没有成功更新。

如果不使用OnPush 更改检测,或者使用changeDetectorRef.detectChanges() 强制刷新更改检测,问题就会消失。不过,这两种解决方案都让人觉得很老套,我真的不明白为什么它不能正常工作。

有问题的示例 repo:https://stackblitz.com/edit/angular-9hwgcn?file=src/app/app.component.html(添加商品后,购物商品列表不会更新)

【问题讨论】:

【参考方案1】:

ChangeDetectionStrategy.OnPush 停止自动更改检测,就像您所经历的那样。它的用例主要是输入/输出组件;它告诉他们仅在 @Input 更改时检测更改。

话虽如此,当我查看您的代码时,

您没有@Input 组件 您的组件没有父/子关系 您正在进行全球运营

然后您停止自动更改检测。在这种情况下,您必须告诉 Angular 需要检测到更改。

所以不,它不是 hacky,是的,它可以正常工作。

尽管如此,如果您想避免所有这些并希望您的代码更具反应性,您可以使用 observables/subjects。这是一个例子:

export class ShoppingListService 
  shoppingListForm: BehaviorSubject<FormArray> = new BehaviorSubject(
    this.fb.array([])
  );
<ng-container *ngIf="shoppingListService.shoppingListForm | async as shoppingListForm">
  <div class="course-item" *ngFor="let shoppingListItem of shoppingListForm.controls">
    <p> shoppingListItem.value | json </p>
  </div>
</ng-container>

Stackblitz

【讨论】:

完美,谢谢。我现在对OnPush 的理解好多了。

以上是关于在服务中使用 FormArray 时的 OnPush 更改检测的主要内容,如果未能解决你的问题,请参考以下文章

带有来自服务的数据的 Angular FormArray setValue

在 formArray Angular 中选择独立的选项

以角度6动态加载formarray中的多个下拉列表

formArray的角异步自定义验证器

formArray 中的可拖动 formGroups(反应式表单)

Angular Material MatChipList - 如何在动态 FormArray 上使用它?