首页 > 解决方案 > 即使输入未更改,DOM 也会在更改检测周期期间使用 OnPush 策略更新视图

问题描述

也许我在 Angular 的变更检测机制中遗漏了一些东西。

我有 2 个组件:

应用组件。

@Component({
  selector: 'my-app',
  template: `
    <button
      (click)="0">
      Async Action in Parent
    </button>

    <child
      [config]="config">
    </child>

    <button
      (click)="mutate()">
      Mutate Input Object
    </button>

  `
})
export class AppComponent  {
  config = {
    state: 0
  };

  mutate() {
    this.config.state = 1;
    console.log(this.config.state);
  }
}

和子组件

@Component({
  selector: "child",
  template: `
    <h1>{{config.state}}</h1>

    <button
      (click)="0">
      Async Action in Child
    </button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})

export class ChildComponent {
  @Input() config;

  ngDoCheck() {
    console.log(`Check`);
  }
}

第1步。

在这里,单击一个按钮时,AppComponent我调用mutate函数,该函数反过来改变传递给嵌套的对象ChildComponent

第2步。

然后我单击同一按钮中的另一个按钮,AppComponent以触发更改检测循环。由于ChildComponent正在使用的OnPush策略和输入参考没有改变,因此在接下来的变化检测中 没有检查ChildComponent视图并且没有更新DOM 插值。到目前为止,它的行为符合我的预期。

但是,如果在第 2 步。我从内部触发更改检测ChildComponent(通过单击适当的按钮),则 检查ChildComponent视图并更新DOM 插值。为什么会这样?自上次以来没有任何变化。

是 StackBlitz 上的演示。

我读过Maxim Koretskyi的一篇关于变更检测精彩文章,但不幸的是它没有回答我的问题。

标签: angularangular2-changedetection

解决方案


触发组件中的 onpush 更改检测的事情(除了输入更改)包括输出事件,这是 click 指令绑定,以及所有其他用户交互指令绑定(滚动、鼠标悬停等)。组件内的超时、间隔或承诺解决方案以及异步管道也是如此。Angular 无法知道输出事件或任何实际更改的内容,因此它假定它确实更改了并运行更改检测周期。


推荐阅读