首页 文章

使用ChangeDetectionStrategy.OnPush在setTimeout中不会触发更改检测

提问于
浏览
2

我有两个组件,我使用ChangeDetectionStrategy.OnPush . 父组件:

@Component({
 changeStaregy: ChangeDetectionStrategy.OnPush,
 template:`
    <button (click)="onClick()">clear</button>
    <div>
        <test [model]="model"></test>
    </div>`
})
export class AppComponent {
    model: TestModel;

    constructor(){
      this.model = { id: 1, text: 'bla bla bla'}
    }

    onClick() {
      this.model = new TestModel();
    }
}

和一个只显示数据的子组件:

@Component({
   changeStrategy: ChangeDetectionStrategy.OnPush,
   selector: 'test',
   template: `
    <div>
          <div> {{model.id}} </div>
           <div> {{model.text}} </div>
    </div>`
})

export class TestComponent {
   @Input() model: TestModel;

}

当我点击“清除”按钮时,它会调用onClick()函数,它将一个空实体分配给“模型” . 这会触发更改检测,因为输入已更改(OnPush策略) . 但是,如果我使用异步调用包装赋值,则更改检测不起作用,因此UI不会更新:

onClick() {
  setTimeout(() => {
    this.model = new TestModel();
  }, 2000);
}

Angular2有NgZone,它修补了setTimeout函数 . 修补后的setTimeout必须触发更改检测,但在我的情况下却没有 . 为什么变化检测不起作用?我该如何解决?

2 回答

  • 2

    由于 changeDetectionStrategy 在父项上设置为 OnPush ,因此更改检测周期在父元素处停止 . 因此,无论其自身设置如何,此父级的任何子级都将策略设置为 OnPush .

    没有 @Input 的父级更改,因此更改检测器不会更深入地朝向父级的子级 . 您应该执行 detectChanges 以使更改生效

  • 1

    使用OnPush更改检测策略时,更改检测仅在输入属性更改时运行,绑定事件是从组件触发或您手动检测更改 .

    在您的示例plunker中,子组件在 changeSetTimeoutchangeModelInZone 中自行更改输入 .

    当您单击按钮时,由于更新了哪个模板,第二次触发有界事件 .

相关问题