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

新手上路,请多包涵

我似乎无法捕获 Window 滚动事件。在几个网站上,我发现了类似这样的代码:

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

这些片段通常来自版本 2。这在 Angular 4.2.2 中似乎(不再起作用?)。例如,如果我将“window:scroll”替换为“window:touchmove”,那么 touchmove 事件就会得到很好的处理。

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

原文由 Robert 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 750
2 个回答

可能您的 document 没有滚动,但里面的 div 是。如果从 --- 调用,滚动事件只会冒泡到 window document 。此外,如果您从 document 捕获事件并调用类似 stopPropagation 的内容,您将不会在 window 中收到事件。

如果要捕获应用程序中的所有滚动事件,这些事件也来自微小的可滚动容器,则必须使用默认的 addEventListener 方法,并将 useCapture 设置为 true .

这将在 DOM 下降时触发事件,而不是气泡阶段。不幸的是,坦率地说,这是一个很大的失误,角度不提供传递事件侦听器选项的选项,因此您必须使用 addEventListener

 export class WindowScrollDirective {

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

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

    scroll = (event): 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 规范,这使得将对象作为 第三个参数 传递成为可能。

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

在我向您展示如何做到这一点之前,您可以想到另一个性能特征。为了防止更改检测运行(每次在区域内发生异步事件时都会调用 DoCheck 。就像事件触发一样),您应该在区域外运行事件侦听器,并且仅在真正需要时才输入它. Soo,让我们把所有这些东西结合起来:

 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();
           });
        }
    };
}

原文由 Poul Kruijt 发布,翻译遵循 CC BY-SA 4.0 许可协议

以防万一我想捕捉一个无法滚动的元素上的滚轮动作,因为它没有滚动条……

所以,我需要的是:

 @HostListener('mousewheel', ['$event'])
onMousewheel(event) {
     console.log(event)
}

原文由 Dan Ortega 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题