[英]Angular change detection triggered by dummy method?
Hello, I try to understand the change detection of angular.你好,我试着了解一下angular的变化检测。
I have a parent component my-editable
for inline text edit and a child component my-input
with a styled input element.我有一个用于内联文本编辑的父组件
my-editable
和一个带有样式输入元素的子组件my-input
。 I'm working with reactive forms which is piped from parent to child component.我正在使用从父组件到子组件的反应式 forms。
Now if the output property status
from child component emit a new event, my parent component call its method dummy()
without any expression.现在,如果来自子组件的 output 属性
status
发出一个新事件,我的父组件将调用它的方法dummy()
而没有任何表达式。
What me confused is that the change detection in parent obviously triggered!我感到困惑的是,父母的变化检测显然被触发了!
If I remove the line (status)="dummy()"
from my-editable.component.html
the error message ( <small class="error">{{ formControl.errors.msg }}</small>
) in template wouldn't be shown.如果我从
my-editable.component.html
中删除行(status)="dummy()"
,则模板中的错误消息( <small class="error">{{ formControl.errors.msg }}</small>
)不会显示。
In my opinion, the change detection should be triggered by (status)="cdr.detectChanges()"
or something similar.在我看来,更改检测应该由
(status)="cdr.detectChanges()"
或类似的东西触发。
Can anyone explain it to me?谁能给我解释一下?
my-input.component.ts
@Component({
selector: 'my-input',
...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyInput implements OnInit, OnDestroy {
...
@Input('control')
set control(control: AbstractControl) {
this.formControl = control as FormControl;
this.formGroup = control.parent;
}
@Output('status') statusOutput = new EventEmitter<string>();
set status(status: string) {
if (status) {
this.statusOutput.emit(status);
this.statusClass = status.toLowerCase();
this.cdr.detectChanges();
} else {
this.statusClass = false;
}
}
public statusClass: false | string;
public formGroup: FormGroup | FormArray;
public formControl: FormControl;
...
constructor(
...
private cdr: ChangeDetectorRef
) {...}
public ngOnInit(): void {
this.status = this.formControl.status;
this.updateOnStatusChange();
...
}
...
private updateOnStatusChange(): void {
this.formControl.statusChanges
.pipe(pairwise(), untilDestroyed(this))
.subscribe(([lastStatus, status]) => {
if (status !== lastStatus) {
this.status = status;
}
});
}
}
my-input.component.html
<i [ngClass]="statusClass" *ngIf="statusClass"></i>
<input [formControl]="formControl" [placeholder]="placeholder">
my-editable.component.ts
@Component({
selector: 'my-editable',
...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyEditableComponent {
...
@Input('control')
set control(control: AbstractControl) {
this.formControl = control as FormControl;
}
...
public formControl: FormControl;
...
public dummy() {} // <<< MAGIC
...
}
my-editable.component.html
...
<ng-container [ngSwitch]="currentMode">
<ng-template [ngSwitchCase]="EditModes.READONLY">
<p>{{ formControl.value }}</p>
</ng-template>
<ng-template [ngSwitchCase]="EditModes.EDITABLE">
<div class="wrapper">
<p>{{ formControl.value }}</p>
<button (click)="mode = EditModes.EDIT">
<i class="edit"></i>
</button>
</div>
</ng-template>
<ng-template [ngSwitchCase]="EditModes.EDIT">
<my-input
(status)="dummy()" <!-- MAGIC -->
[control]="formControl"
...
></my-input>
</ng-template>
</ng-container>
<ng-container [ngSwitch]="formControl.invalid && formControl.touched">
<ng-template [ngSwitchCase]="true">
<small class="error">{{ formControl.errors.msg }}</small>
</ng-template>
<ng-template [ngSwitchCase]="false">
<small class="description">{{ description }}</small>
</ng-template>
</ng-container>
Just watched this awesome talk yesterday.昨天刚看了这个精彩的演讲。
You should find your answer somewhere between 14:30 and 17:00.你应该在 14:30 到 17:00 之间找到答案。
TLDR : when you have OnPush
, change detection will trigger when @Input
data changes , but also when internal events occur . TLDR :当您有
OnPush
时,更改检测将在@Input
数据更改时触发,而且在内部事件发生时也会触发。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.