我一直在进行一项与Angular组件中处理状态相关的小实验。
假设我的计算成本很高,取决于其他几个。我可以编写一个函数updateVar()
并在我知道可能影响它的每个事件上调用它,例如。通过订阅。但是当在超过5个不同的地方调用上述函数时,它感觉不是很干,也不健壮。
相反,如何去抖动DoCheck
Angular生命周期钩子?
docheckSubject: Subject<any> = 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()正在发生,而Protractor测试也没有抱怨。但我无法摆脱做一个肮脏的不那么聪明的黑客的感觉。
问题:这会咬我吗?事实上,我是否真的需要它?
答案 0 :(得分:1)
ngDoCheck
经常被调用:
https://angular.io/guide/lifecycle-hooks#docheck
This hook is called with enormous frequency—after every change detection cycle no matter where the change occurred.
将此钩子用于Angular不知道的变量检测变量之外的其他任何东西都是一个坏主意。 (例如,输入对象更改其某个属性的值)。 Debouncing有点帮助,但你仍然经常执行那个逻辑,并且在你不再需要它之后会继续这样做(即debounced == false
时)。
我认为您的解决方案可行,但我认为这种方法的开销远远低于替代方案。可能值得将更新逻辑作为Observable
链的一部分,或将Observables
传递给将该逻辑添加到链中的函数。
答案 1 :(得分:1)
经过几个月的生产没有问题(AFAICT),我最终删除它,因为它最终导致e2e(量角器)测试阻止,直到有人手动点击页面。显然不可持续。
我无法正确诊断此问题的原因,它可能源于我们代码中不相关部分的怪癖,但比抱歉更安全。
答案 2 :(得分:0)
你可以把变量放在一个getter中,只在重新计算时才重新计算吗?
这是一个简单的例子:
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div>x={{x}}</div>
<div>y={{y}}</div>
<button (click)="increment()">Increment</button>
<div>Calculated Value={{calculatedValue}}</div>
</div>
`,
})
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