onPush检测策略在角度8中不起作用

时间:2019-09-15 07:56:45

标签: angular performance angular8 rxjs6 angular2-changedetection

我正在用angular 8创建一个应用程序,目前正在仪表板模块上工作,那里有一个onPush Strategy似乎不起作用的场景,如果有人可以帮助我,我将用div结构来说明我的场景。< / p>

<div class="parent" *ngFor="dashcontent of dashbboardsData">

<app-widget-body [widget]="dashcontent.widget"></app-widget-body>


</div>


<div class="sidebar"> 

<app-sidebar [(selectedWidget)]="dashbboardsData[0].widget">

<app-widget-settings [(widget)]="selectedWidget"></app-settings>

</app-sidebar>

</div>

以上是我在 app-widget-settings 组件中更改widget.widgetName的情况,其中app-widget-settings由与 widget.widgetName <绑定的文本框组成/ strong>使用 ngModel

<input type="text" [(ngModel)]="widget.widgetName">

在这里,但我所做的更改未反映在我正在使用的 app-widget-body 组件中

changeDetection: ChangeDetectionStrategy.OnPush

如果我要从app-widget-body中删除changeDetection,则会反映出更改。

因此,在上面我们应该使用什么,以便在 app-widget-body 组件中反映出在 app-widget-settings 组件中所做的更改,而我想使用ChangeDetectionStrategy.OnPush。

下面是stackblitz的链接

  

https://stackblitz.com/edit/angular-gjdjzg?file=src%2Fapp%2Fapp.component.ts

3 个答案:

答案 0 :(得分:1)

这实际上是预期的行为。

每个组件都有自己的变更检测参考,将策略更改为OnPush策略时,必须记住,要使变更检测器“打勾”,您必须传递新的参考输入的内容。

在这种情况下,您只需编辑窗口小部件的属性之一,但并没有真正更改其引用。

尝试在每次更改窗口小部件对象时发出一个事件,然后在容器组件中仅返回一个覆盖该更改的新对象。像这样:

onNameChange(name: string){
   this.widget = {...this.widget, widgetName: name}
}

答案 1 :(得分:1)

您需要“填充”对仪表板组件的更改,以便重新加载(更改其引用)其小部件数组:

https://stackblitz.com/edit/angular-mzxcbd

这很乏味,也不是很漂亮。通常,不建议将其用于深度嵌套的对象。一个很好的替代方法是将Redux模式与NGRX一起使用。 中央存储区保存您的数据,任何组件都可以独立于其层次结构访问数据。我强烈推荐它。

答案 2 :(得分:1)

使用ChangeDetectionStrategy.OnPush时,必须遵循规则 '不是来自@Input()的每个变量都在模板中使用,并且可能在组件的生命周期中更改,应该在模板中作为具有管道异步的流(可观察到)'

>

Angular还具有3类反应数据:

  • FormArray-用于数组
  • FormGroup-用于地图
  • FormControl-用于简单值

请注意,您仅应仅通过提供的API(例如FormControl.setValue(value))修改这些类中的数据,以使它们发出更改事件,这将告诉异步管道触发更改检测周期

在您的情况下,我将使用FormGroup的FormGroup元素,每个字段都具有FormControl。

访问字段就像

<div class="parent" *ngFor="widgetFormGroupIndex of widgetIndexList">
  {{ dataFormArray.at(widgetFormGroupIndex).get('widgetName').valueChanges | async }}
</div>

同样,您应该在输入中使用ReactiveFormsModule中的指令,像这样

<input type="text" [formControl]="dataFormArray.at(widgetFormGroupIndex).get('widgetName')">

有关更多信息,请阅读https://angular.io/guide/reactive-forms

还请注意,您不应在模板中调用方法(它在每个更改检测周期都调用它们),代码使用方法是为了简化。代替功能调用,您应该创建纯管道(有关更多信息,请点击此处https://angular.io/guide/pipes),或者在component.ts文件中预先计算功能调用结果,然后在模板中使用结果