再现性
我有一个小的 TypeScript 代码片段,如下所示:
ngAfterViewChecked(){
console.log("ngAfterViewChecked 1");
setTimeout(() => {
console.log("ngAfterViewChecked 2");
}, 1000);
}
功能
setTimeOut()
应该在 1 秒后调用 lambda 函数然后停止。然而,钩子(Hook) ngAfterViewChecked() 被连续调用(摘自 Chrome 开发者工具控制台):00:36:50.827 home.component.ts:53 ngAfterViewChecked 1
00:36:51.842 home.component.ts:55 ngAfterViewChecked 2
00:36:51.843 home.component.ts:53 ngAfterViewChecked 1
00:36:52.843 home.component.ts:55 ngAfterViewChecked 2
00:36:52.844 home.component.ts:53 ngAfterViewChecked 1
00:36:53.845 home.component.ts:55 ngAfterViewChecked 2
00:36:53.846 home.component.ts:53 ngAfterViewChecked 1
00:36:54.848 home.component.ts:55 ngAfterViewChecked 2
...
没有
setTimeOut()
, 功能 ngAfterViewChecked()
被调用一次。 ngDoCheck()
也会出现此问题, ngAfterContentChecked()
.使用其他 Angular 生命周期钩子(Hook)进行测试
相同的代码体,有或没有
setTimeOut()
, 在 constructor()
中声明, ngOnInit()
, ngAfterContentInit()
, ngAfterViewInit()
,按预期被调用一次。环境
Angular CLI: 6.0.8
Node: 8.11.3
OS: win32 x64
Angular: 6.0.9
Angular CLI: 1.7.4
Node: 8.11.1
OS: win32 x64
Angular: 5.2.10
我猜
Hook
constructor()
, ngOnInit()
, ngAfterContentInit()
, ngAfterViewInit()
在组件的整个生命周期中调用一次,无论其内容在其生命周期中如何演变。所以这个问题合理地不会在这些钩子(Hook)中发生。与
ngDoCheck()
, ngAfterContentChecked()
和 ngAfterViewChecked()
,当 Angular 检测到更改时,它们会被调用。但正如 lambda 函数体所示,只有简单的 console.log()
用来。我认为 Angular 可能会拦截 setTimeOut()
调用并盲目地认为可能发生了一些变化,因此它启动了更改检测过程,这导致了我们所看到的:调用无限链接。问题
这是错误还是功能?
最佳答案
功能 - Angular 的更改检测在异步操作完成后运行(如 setTimeout) - 所以 setTimeout 本身会导致 ngAfterViewChecked
运行,反之亦然。
如果您不希望这种情况发生,您可以在 Angular 的区域之外运行,即
ngAfterViewChecked(){
console.log("ngAfterViewChecked 1");
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
console.log("ngAfterViewChecked 2");
}, 1000);
});
}
您可以在构造函数中注入(inject) NgZone,即
private ngZone: NgZone
.查看 Angular 和 zone.js 之间的关系以获取更多信息。
关于angular - setTimeOut() 在 Angular Lifecycle Hooks : ngDoCheck, ngAfterContentChecked, ngAfterViewChecked 中重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51333858/