如何处理Angular 4中的窗口滚动事件?

问题描述:

我似乎无法捕捉到窗口滚动事件。在角4.2.2经常如何处理Angular 4中的窗口滚动事件?

@HostListener("window:scroll", []) 
onWindowScroll() { 
    console.log("Scrolling!"); 
} 

的片断来自第2版。这似乎不工作(再): 在几个网站,我发现类似这样的代码。如果我用“window:touchmove”替换“window:scroll”,然后touchmove事件处理正常。

有谁知道我错过了什么?非常感谢你!

也许你的document不滚动,但它内部是div。如果从document调用该滚动事件,则该滚动事件仅起泡至window。另外,如果您从document中捕获事件并拨打stopPropagation之类的东西,则您将不会收到window中的事件。

如果你想捕捉你的应用程序内的所有滚动事件,这也将是从微小的滚动容器,你必须使用默认的addEventListeneruseCapture设置为true

这会在事件发生时触发DOM而不是泡泡阶段。不幸的是,很坦率地说大小姐,角度不提供一个选项,在事件监听器选项传递,所以你必须使用addEventListener

export class WindowScrollDirective { 

    ngOnInit() { 
     window.addEventListener('scroll', this.scroll, true); //third parameter 
    } 

    ngOnDestroy() { 
     window.removeEventListener('scroll', this.scroll, true); 
    } 

    scroll =(): void => { 
     //handle your scroll here 
     //notice the 'odd' function assignment to a class field 
     //this is used to be able to remove the event listener 
    }; 

} 

现在,这是不是所有有它,因为所有的主要的浏览器(IE和Edge除外)已经实现了新的addEventListener规范,这使得可以传递一个对象为third parameter

使用此对象可以将事件侦听器标记为passive。这是一个推荐的事情,这个事件会触发很多时间,这会干扰UI性能,例如滚动事件。要实现这一点,你应该首先检查当前浏览器是否支持这个功能。在mozilla.org上,他们发布了一个方法passiveSupported,您可以使用它来检查浏览器支持。你只能使用这个,当你确定你不打算使用event.preventDefault()

在我告诉你如何做到这一点之前,还有另一个你可以想到的性能特征。为防止运行中发生变化检测(每次在区域内发生异步事件时都会调用DoCheck,就像事件触发一样),您应该在区域外运行事件侦听器,并且只有在真正有必要时才会输入事件侦听器。所以,让我们结合所有这些东西:

export class WindowScrollDirective { 

    private eventOptions: boolean|{capture?: boolean, passive?: boolean}; 

    constructor(private ngZone: NgZone) {} 

    ngOnInit() {    
     if (passiveSupported()) { //use the implementation on mozilla 
      this._eventOptions = { 
       capture: true, 
       passive: true 
      }; 
     } else { 
      this.eventOptions = true; 
     } 
     this.ngZone.runOutsideAngular(() => { 
      window.addEventListener('scroll', this.scroll, <any>this.eventOptions); 
     }); 
    } 

    ngOnDestroy() { 
     window.removeEventListener('scroll', this.scroll, <any>this.eventOptions); 
     //unfortunately the compiler doesn't know yet about this object, so cast to any 
    } 

    scroll =(): void => { 
     if (somethingMajorHasHappenedTimeToTellAngular) { 
      this.ngZone.run(() => { 
       this.tellAngular(); 
      }); 
     } 
    }; 
} 
+0

非常感谢你,这似乎按预期工作!我认为这个问题的确是文件本身不会在我的情况下滚动。 – Robert

+1

@Robert我已经用更多信息更新了我的答案:) – PierreDuc

+0

第二个代码块中的侦听器中的内容是否与拦截事件相关?此外,如何确定滚动的方向? –