【问题标题】:How to prevent change detection on scroll? ( Angular )如何防止滚动上的更改检测? (角)
【发布时间】:2019-05-28 09:32:09
【问题描述】:

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

我将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');
}

即使this.updateStyle 是一个空函数,也会调用ngAfterViewChecked。 但是如果我注释掉this.my_element_ref.nativeElement.addEventListener('scroll', this.onScroll),那么ngAfterViewChecked就不会再被调用了。

如何在元素滚动时调用函数,但避免 Angular 的变化检测?

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    我建议你使用 ngZone.runOutsideAngular。

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

    【讨论】:

      【解决方案2】:

      您可能想查看 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

      【讨论】:

        【解决方案3】:

        只需在构造函数中注入NgZone,然后订阅这样的事件:

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

        请记住,在这种情况下不会调用更改检测,因此您将无法使用模板绑定更改样式。应该通过原生 javascript 或使用Renderer2

        进行更改

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-31
          • 1970-01-01
          • 1970-01-01
          • 2022-08-08
          • 2019-11-20
          • 2017-05-25
          • 1970-01-01
          • 2016-01-06
          相关资源
          最近更新 更多