angular - 由虚拟方法触发的角度变化检测?
问题描述
您好,我尝试了解角度的变化检测。
我有一个my-editable
用于内联文本编辑的父组件和一个my-input
带有样式输入元素的子组件。我正在使用从父组件到子组件的反应式表单。
现在,如果子组件的输出属性status
发出一个新事件,我的父组件会调用它的方法dummy()
而无需任何表达式。
我感到困惑的是,父母的变化检测显然被触发了!
如果我(status)="dummy()"
从模板中my-editable.component.html
的错误消息 ( <small class="error">{{ formControl.errors.msg }}</small>
) 中删除该行,则不会显示。
在我看来,变更检测应该由(status)="cdr.detectChanges()"
类似的东西触发。
谁能给我解释一下?
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>
解决方案
推荐阅读
- javascript - 数组对象的碰撞检测
- android - How to make set TextView.text persistent in Android app (Kotlin)
- sql - 无法显示区域容量为零
- python - 如何获取图像中的边框像素或擦除区域
- javascript - 按钮提交后如何刷新CSS?
- javascript - 无法使用三元条件读取“未定义”的属性 x?
- javascript - 如何设置跨站点cookies?
- function - Python中的Azure函数获取镶木地板文件的架构
- python - 获取上一页点击的超链接名称-FLASK
- css - 包含 CSS 属性的对象的类型