我似乎无法捕获窗口滚动事件.
@HostListener("window:scroll", [])
onWindowScroll() {
console.log("Scrolling!");
}
这些片段通常来自版本2.这似乎不起作用了(再也不起作用了?)在4.2.2中.例如,如果我将"window:scroll"替换为"window:touchmove",那么touchmove事件处理得很好.
有人知道我错过了什么吗?非常感谢你!
我似乎无法捕获窗口滚动事件.
@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();
});
}
};
}