我似乎无法捕获窗口滚动事件.

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

这些片段通常来自版本2.这似乎不起作用了(再也不起作用了?)在4.2.2中.例如,如果我将"window:scroll"替换为"window:touchmove",那么touchmove事件处理得很好.

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

推荐答案

也许你的document没有滚动,但里面有div.如果从document调用滚动事件,则滚动事件只会冒泡到window.此外,如果您从document中捕获事件并调用类似stopPropagation的东西,那么您将不会在window中收到事件.

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

这将触发事件时,它下降到DOM,而不是泡沫阶段.不幸的是,坦率地说,angular没有提供传递事件侦听器选项的选项,因此您必须使用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规范,这使得将一个对象传递为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();
           });
        }
    };   
}

Typescript相关问答推荐

使用前的组件渲染状态更新

带有联合参数的静态大小数组

如何判断输入是否是TypeScript中的品牌类型?

如何在TypeScrip中使用嵌套对象中的类型映射?

ANGLE找不到辅助‘路由出口’的路由路径

获取函数中具有动态泛型的函数的参数

尽管对象的类型已声明,但未解析的变量<;变量

如何通过TypeScrip中的函数防止映射类型中未能通过复杂推理的any值

避免混淆两种不同的ID类型

如何在不违反挂钩规则的情况下动态更改显示内容(带有状态)?

如何为特定参数定义子路由?

打印脚本中正则函数和函数表达式的不同类型缩小行为

在Google授权后由客户端接收令牌

KeyOf关键字在特定示例中是如何工作的

有没有一种方法可以防止我的组件包在其中安装样式组件'; node 模块中的s目录

如何实现允许扩展泛型函数参数的类型

什么';是并类型A|B的点,其中B是A的子类?

确保财产存在

如何从联合类型推断函数参数?

为什么 TypeScript 类型条件会影响其分支的结果?