繁体   English   中英

Angular 未使用 OnPush 策略为后代触发更改检测

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM