admin管理员组

文章数量:1426043

I have a large ponent, and I would like to avoid unnecessary change detections to increase performance.

I added changeDetection: ChangeDetectionStrategy.OnPush to the @Component.

I would like to update the style of an element if it is scrolled. Unfortunately Angular runs the change detection, every time I scroll that element.

I tried to add an event listener to the native element to avoid this, but the change detection is still running again when I scroll:

@ViewChild('my_element') my_element_ref: ElementRef;

ngOnInit() {
    this.my_element_ref.nativeElement.addEventListener('scroll', this.updateStyle);
}

ngAfterViewChecked() {
    console.log('check');
}

The ngAfterViewChecked is called even if this.updateStyle is an empty function. But if I ment out this.my_element_ref.nativeElement.addEventListener('scroll', this.onScroll), then ngAfterViewChecked is not called anymore.

How is it possible to call a function when an element is scrolled, but avoid Angular's change detection?

I have a large ponent, and I would like to avoid unnecessary change detections to increase performance.

I added changeDetection: ChangeDetectionStrategy.OnPush to the @Component.

I would like to update the style of an element if it is scrolled. Unfortunately Angular runs the change detection, every time I scroll that element.

I tried to add an event listener to the native element to avoid this, but the change detection is still running again when I scroll:

@ViewChild('my_element') my_element_ref: ElementRef;

ngOnInit() {
    this.my_element_ref.nativeElement.addEventListener('scroll', this.updateStyle);
}

ngAfterViewChecked() {
    console.log('check');
}

The ngAfterViewChecked is called even if this.updateStyle is an empty function. But if I ment out this.my_element_ref.nativeElement.addEventListener('scroll', this.onScroll), then ngAfterViewChecked is not called anymore.

How is it possible to call a function when an element is scrolled, but avoid Angular's change detection?

Share Improve this question asked May 28, 2019 at 9:32 Iter AtorIter Ator 9,34822 gold badges89 silver badges184 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 2

I would suggest you use ngZone.runOutsideAngular.

constructor (private zone : NgZone) {}
ngAfterViewInit () : any {
    this.zone.runOutsideAngular(() => {
      window.addEventListener('scroll', (e)=> {
        console.log( 'scroll event fired' );
      });
    });
  }

You might want to look at ChangeDetectorRef API. Specifically you would detach the change detection for the ponent using detach() (maybe in the constructor like below) and then mark ponent for change in your scroll function via markForCheck().

  constructor(public cd: ChangeDetectorRef) {
    this.cd.detach();
  }

this.cd.markForCheck(); 

Below links for your reference.

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

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

just inject NgZone in your constructor and then subscribe to an event like this:

this.ngZone.runOutsideAngular(() => {
  ....addEventListener('...);
});

keep in mind that change detection will not be called in this case, so you won't be able to change styles with template binding. It should be changed by native javascript or using Renderer2

本文标签: javascriptHow to prevent change detection on scroll ( Angular )Stack Overflow