我正在用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
答案 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类反应数据:
请注意,您仅应仅通过提供的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文件中预先计算功能调用结果,然后在模板中使用结果