Debounce Angular ngDoCheck lifecycle hook
我一直在进行一些有关在Angular组件中处理状态的实验。
假设我有一个计算成本很高的变量,它取决于其他几个变量。 我可以编写一个函数
因此,反跳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | docheckSubject: Subject = new Subject(); debounced: boolean = false; constructor(private cd: ChangeDetectorRef) {} ngOnInit() { this.docheckSubject.debounceTime(50).subscribe( () => this.ngDoCheckDebounced() ); } ngDoCheck() { if (!this.debounced) { this.docheckSubject.next(); } else { this.debounced = false; } } ngDoCheckDebounced() { this.debounced = true; this.updateVar(); this.cd.detectChanges(); // needed to reflect update in DOM } |
这是一个小例子。
这种方法在我的真实应用中似乎可以正常工作,当然,更多的ngDoCheck()正在发生,并且量角器测试也不会抱怨。 但是我无法摆脱做一个肮脏,不太聪明的黑客的感觉。
问:这会咬我吗? 实际上,我是否需要它?
经过几个月没有问题的生产(AFAICT),我最终删除了它,因为它最终导致e2e(量角器)测试受阻,直到有人手动单击页面。显然是不可持续的。
我无法正确诊断此问题的原因,它可能是源于我们代码中无关部分的怪异现象,但是比后悔更安全。
https://angular.io/guide/lifecycle-hooks#docheck
将此钩子用于除Angular不知道的变量以外的其他任何东西以寻找变更检测是一个坏主意。 (例如,输入对象更改其属性之一的值)。防弹跳有所帮助,但是您仍然非常频繁地执行该逻辑,并且在不再需要该逻辑时(例如,当
我认为您的解决方案可以使用,但是我认为这种方法的开销比其他方法差得多。可能值得将更新逻辑作为
您能否将变量放入getter中,并且仅在检索到变量时重新计算?
这是一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | //our root app component import {Component, NgModule, VERSION} from '@angular/core' import {BrowserModule} from '@angular/platform-browser' @Component({ selector: 'my-app', template: ` Hello {{name}} x={{x}} y={{y}} <button (click)="increment()">Increment</button> Calculated Value={{calculatedValue}} `, }) export class App { name:string; x: number = 0; y: number = 10; get calculatedValue(): number { return this.x * this.y; } constructor() { this.name = `Angular! v${VERSION.full}` } increment(): number { this.x++; } } |
以及相关的Plunker:https://plnkr.co/edit/QC7mkbsbjRRBjJOjWSHe?p=preview