如何防止滚动检测变化? (角度)

时间:2019-05-28 09:32:09

标签: javascript angular

我的组件很大,我想避免不必要的更改检测以提高性能。

我将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的更改检测?

3 个答案:

答案 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(); 

下面的链接供您参考。

https://blog.angularindepth.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f

https://angular.io/api/core/ChangeDetectorRef