【问题标题】:Angular change detection: why is entire tree checked on local changes?角度变化检测:为什么要检查整个树的局部变化?
【发布时间】:2017-12-23 10:58:54
【问题描述】:

假设我有一个简单的文本数组:

textContent = [
    {text: 'good morning'},
    {text: 'lovely day'},
    {text: 'for debugging'},
  ]

我为每个渲染一个简单的组件,将文本项作为输入传递:

<app-text *ngFor="let text of textContent" [text]="text"></app-text>

文本组件渲染文本,使用 ngModel:

<textarea [(ngModel)]="text.text"></textarea>

我也在登录 DoCheck:

ngDoCheck() {
    console.log(this.text.text, ' has been checked')
}

当我在 one 文本区域中输入内容时,所有其他 组件的 DoCheck 都会被触发。

good morning   has been checked
lovely days    has been checked
for debuggings has been checked

即使使用 OnPush 进行更改检测也会发生这种情况。

问题:为什么对一个组件的数据所做的更改会触发检查整个树?

(对于少数组件来说这不是问题,但是对于更大的树,我会丢帧)。

我实际上注意到,即使是完全独立的内容树上的组件也会触发它们的“doCheck”。

有没有办法防止这种情况发生,还是我完全错过了其他东西?

【问题讨论】:

    标签: angular angular2-changedetection


    【解决方案1】:

    在 Angular 上,每个组件都有自己的变化检测器。这背后的原因是允许我们单独控制每个组件。这意味着我们可以完全控制整个应用程序的每个组件何时发生更改检测。

    虽然这是一个很棒的功能,但当您将 Angular 应用程序视为一组组件或通常称为组件树的东西时,这意味着树中的所有组件都将具有相同的功能。他们自己的个人变化检测机制。当你把它们放在一起时,你基本上让整个树执行更改检测。

    如果没有设置高级技术或配置,Angular 默认使用保守的方法,并在发生更改时触发对整个树的更改检测。

    当然,有一些机制和技术可以让您对此进行更多控制,并且仅当某些内容实际发生更改时并且仅针对特定组件和子组件时才会进行更改检测。

    看看这个article,Pascal Precht 详细解释了变更检测的工作原理。

    有一些技术可以避免您遇到的问题,例如您提到的 onPush 更改检测以及不可变对象和可观察对象的使用。如果要实现对变更检测的完全控制,可以将所有组件设置为具有 onPush 策略。

    【讨论】:

      【解决方案2】:

      我的问题是基于我的误解,所以让我澄清一下:

      当调用组件的 DoCheck() 生命周期钩子时,这并不意味着它已被检测到更改。这仅意味着 Angular 正在执行更改检测运行,并为您提供了机会钩入其中,以执行一些自定义逻辑。

      本文If you think ngDoCheck means your component is being checked — read this article有更多详情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 2018-05-07
        • 2021-08-07
        • 2018-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多