【问题标题】:Reactive formcontrol triggers Change Detection反应式表单控件触发更改检测
【发布时间】:2021-04-07 15:38:04
【问题描述】:

只要输入值发生更改,反应性FormControl 元素就会触发ChangeDetection。我添加了OnPush 策略,但它仍然运行ChangeDetection

@Component({
  selector: 'app-server-input',
  templateUrl: './server-input.component.html',
  styleUrls: ['./server-input.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

FormControl 指令是触发ChangeDetection 的指令。输入更改时如何停止运行ChangeDetection

serverName: FormControl = new FormControl();

这是我在 StackBlitz 上的 code

注意:这里要注意的一点是,如果您单击按钮,则会调用 ngDocheck,因此我使用了事件管理器来停止更改检测。

【问题讨论】:

  • 内部实现似乎触发了 OnPush 更改检测。此时,最好改变您尝试实施解决方案的方式。
  • 请阅读文章,@Robin Dijkhof 是正确答案:indepth.dev/posts/1131/…
  • 你必须明白什么时候没有分配fomcontrol,那么就没有变化检测。

标签: angular angular2-changedetection angular-changedetection


【解决方案1】:

ngDoCheck 总是运行。不管你使用什么策略。见https://indepth.dev/posts/1131/if-you-think-ngdocheck-means-your-component-is-being-checked-read-this-articleWhy do we need `ngDoCheck`

我看不出您想知道更改检测何时运行、运行方式如何的任何原因。如果你想做一些改变,只需在你的输入上使用一个 setter:

_name: string;
get name(): string{
    return this._name;
}
@Input() set name(value: string) {
    this._name = value;
    this.doUpdateSomething();
}

【讨论】:

  • 我在父组件上添加了一个按钮并单击它,然后 ngDocheck 在子组件上运行,但是当我处理了 ngZone 之外的单击事件时,子组件的 nDocheck 没有运行.这个实验证明了 ngDoCheck 并不总是默认运行
  • 您必须了解当没有分配表单控件时,ngDocheck 不会在子组件中运行
【解决方案2】:

我已经分叉并更新了你的代码:https://stackblitz.com/edit/child-component-2bstm4?file=app/app.component.ts

  ngOnInit() {    
    this.zone.runOutsideAngular(() => (
      this.serverName = new FormControl(),
      this.cd.detach()
      )
    );
  }

【讨论】:

  • 与 TypeScript 开发者相比,Angular 开发者还考虑过如果我们放火并关闭火警警报会发生什么。如果您查看 ChangeDetectorRef API,您会发现他们已经考虑了所有可能性。 “分离”就是其中之一:angular.io/api/core/ChangeDetectorRef。所有这些步骤都可以手动启动,在最好的情况下应该自动运行。
  • 我将赏金奖励给这个答案。但这不适用于我的应用程序。
  • StackBlitz 适用于区域,其中 this.cd.detach() 被指定为参数。在您的真实应用中,您必须在创建表单之前放置​​它。
  • 这是我的 stackblitz -> stackblitz.com/edit/…
  • 我已经尝试过使用 cd.detach,但它不起作用。
【解决方案3】:

为了防止 Angular 在每次用户与输入字段交互时运行变化检测,您应该分离变化检测器。 你需要注入 ChangeDetectorRef 并调用它的 detach 方法

  constructor(private cd: ChangeDetectorRef) {}
  ngOnInit() {
    this.cd.detach();
  }

将不再为该组件及其子组件自动运行更改检测。 当您需要触发更改检测时,您可以调用 ChangeDetectorRef 上的 detectChanges 方法。

例如,这将每 5 秒触发一次更改检测。

  ngOnInit() {
    this.cd.detach();
    setInterval(() => this.cd.detectChanges(), 5000);
  }

【讨论】:

  • 这根本不相关。
【解决方案4】:

在下面提到的链接中,有一个选项可以禁用表单控件上的更改检测

disable form control

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 2020-11-22
    • 2019-01-22
    • 2021-09-02
    • 2011-10-04
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多