[英]Angular change detection not triggered for descendents with OnPush strategy
我在表单组件上使用 angular 指令,当它们被提交时,它们的表单组和所有输入都被标记为已触及。 这是组件:
import { Directive, HostListener, Self } from '@angular/core';
import { ControlContainer } from '@angular/forms';
@Directive({
selector: 'form[formGroup]',
})
export class MarkAllAsTouchedDirective {
@HostListener('submit')
onSubmit(): void {
this.container.control?.markAllAsTouched();
this.cdr.detectChanges();
}
constructor(
@Self() private container: ControlContainer,
private cdr: ChangeDetectorRef
) {}
}
现在在我的应用程序中,我在我的表单组件中嵌套了一个具有OnPush
更改检测策略的组件。 几乎像下面这样:
<form
[formGroup]="someForm"
(ngSubmit)="onSubmit()"
>
<app-account-form
[someForm]="someForm"
></app-account-form>
.
.
.
</form>
而具有OnPush
策略的app-account-form
组件如下:
import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-account-form',
templateUrl: './account-form.component.html',
styleUrls: ['./account-form.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccountFormComponent {
@Input() someForm!: FormGroup;
}
我的问题是app-account-form
组件没有检测到对someForm
表单组所做的更改,即使我在上面的MarkAllAsTouchedDirective
指令中调用detectChanges
方法也是如此。
这里有什么问题? 我是否误解了detectChanges
的实现以及它是否适用于所有后代?
ChangeDetectorReference.detectChanges() 通过遵守子组件的 CD 策略在组件及其子组件上触发 CD。 由于AccountFormComponent
具有 OnPush 策略,因此只有在someForm
输入更改时才会将其标记为更改。 为了确定输入是否改变,Angular 做了一个简单的===
比较,它不是深度 object 比较。 在您的情况下,即使someForm
object 的 touch 属性已更改,引用仍然相同,因此不会将AccountFormComponent
标记为已检查。
这是 Angular 中进行比较的代码,引用自这篇关于 Change Detection 的精彩文章。
要获得有关 CD 的更多见解:
Angular DevTools for Chrome提供了一个分析器,它列出了所有更改检测事件,显示每个事件的来源,还允许您查看在每个 CD 周期中检查了哪个组件。 只需确保 select “火焰图”并勾选“仅显示变化检测”复选框。 标记为蓝色的组件已经过检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.