我的组件很大,我想避免不必要的更改检测以提高性能。
我将changeDetection: ChangeDetectionStrategy.OnPush
添加到了@Component
。
如果元素滚动,我想更新它的样式。不幸的是,每当我滚动该元素时,Angular都会运行更改检测。
我尝试向本机元素添加事件侦听器以避免这种情况,但是当我滚动时,更改检测仍在运行:
@ViewChild('my_element') my_element_ref: ElementRef;
ngOnInit() {
this.my_element_ref.nativeElement.addEventListener('scroll', this.updateStyle);
}
ngAfterViewChecked() {
console.log('check');
}
即使ngAfterViewChecked
是一个空函数,也会调用this.updateStyle
。
但是,如果我注释掉this.my_element_ref.nativeElement.addEventListener('scroll', this.onScroll)
,那么就不再调用ngAfterViewChecked
。
滚动元素时如何调用函数,但避免Angular的更改检测?
答案 0 :(得分:1)
我建议您使用ngZone.runOutsideAngular。
constructor (private zone : NgZone) {}
ngAfterViewInit () : any {
this.zone.runOutsideAngular(() => {
window.addEventListener('scroll', (e)=> {
console.log( 'scroll event fired' );
});
});
}
答案 1 :(得分:1)
只需在构造函数中注入NgZone
,然后订阅这样的事件:
this.ngZone.runOutsideAngular(() => {
....addEventListener('...);
});
请记住,在这种情况下不会调用更改检测,因此您将无法使用模板绑定来更改样式。应该通过本机JavaScript或使用Renderer2
答案 2 :(得分:1)
您可能想看看ChangeDetectorRef API。 具体来说,您可以使用detach()分离组件的更改检测(可能在下面的构造函数中),然后通过markForCheck()在滚动功能中标记要更改的组件。
constructor(public cd: ChangeDetectorRef) {
this.cd.detach();
}
this.cd.markForCheck();
下面的链接供您参考。