gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 16:42:04 25 4
gpt4 key购买 nike

我有两个组件,我在其中使用 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 必须触发更改检测,但就我而言,它不会。为什么变化检测不起作用?我该如何修复它?

最佳答案

以下是您的场景中所发生情况的步骤:

  1. 绑定(bind)的单击事件在触发时会将组件及其祖先标记为脏。这发生在执行 onClick() 方法之前。
  2. 执行onClick()方法后,Angular调用ApplicationRef.tick()来启动更改检测。由于祖先组件被标记为脏,因此更改检测会发生在 OnPush 组件上。请记住,此时 setTimeout 回调尚未执行。
  3. 更改检测完成后,组件不再“脏”。然后执行 setTimeout 回调。 setTimeout 回调完成后,调用 ApplicationRef.tick() 再次启动更改检测。但是,由于您的 AppComponent 标记为 OnPush,并且没有 @Input 更改(因为 AppComponent 没有输入),并且组件及其祖先未标记为脏,因此更改检测不会进行直到子组件。因此对 this.model 的更改不会反射(reflect)在 DOM 中。

我发现这很有帮助: https://www.mokkapps.de/blog/the-last-guide-for-angular-change-detection-you-will-ever-need

关于angular - 使用 ChangeDetectionStrategy.OnPush 在 setTimeout 中不会触发更改检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45281469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com