我似乎无法捕获Window滚动事件。 在几个网站上,我发现代码与此类似:
@HostListener("window:scroll", [])
onWindowScroll() {
console.log("Scrolling!");
}
这些片段通常来自版本2.这在Angular 4.2.2中似乎不起作用(不再?)。如果我将“window:scroll”替换为“window:touchmove”,那么touchmove事件处理得很好。
有谁知道我错过了什么?非常感谢你!
答案 0 :(得分:60)
您的document
可能不会滚动,但其中只有div
。如果从window
调用滚动事件,则仅向document
冒泡。此外,如果您从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 = (): 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();
});
}
};
}
答案 1 :(得分:9)
如果您恰巧是 使用角材料 ,则可以执行以下操作:
import { ScrollDispatchModule } from '@angular/cdk/scrolling';
在Ts:
import { ScrollDispatcher } from '@angular/cdk/scrolling';
constructor(private scrollDispatcher: ScrollDispatcher) {
this.scrollDispatcher.scrolled().subscribe(x => console.log('I am scrolling'));
}
在模板中:
<div cdkScrollable>
<div *ngFor="let one of manyToScrollThru">
{{one}}
</div>
</div>
答案 2 :(得分:4)
我还没有评论。 @PierreDuc是您的答案,除非@Robert表示文档不会滚动。我对您的答案做了一些修改,以使用侦听器发送的事件,然后监视源元素。
ngOnInit() {
window.addEventListener('scroll', this.scrollEvent, true);
}
ngOnDestroy() {
window.removeEventListener('scroll', this.scrollEvent, true);
}
scrollEvent = (event: any): void => {
const number = event.srcElement.scrollTop;
}
答案 3 :(得分:1)
在角度8中,实现此代码,以我为例,它可以正常使用滚动来更改导航栏的颜色... 您的模板:
<div class="level" (scroll)="scrolling($event)" [ngClass]="{'level-trans': scroll}">
<!-- your template -->
</div>
您的.ts
export class HomeNavbarComponent implements OnInit {
scroll:boolean=false;
constructor() { }
ngOnInit() {
window.addEventListener('scroll', this.scrolling, true)
}
scrolling=(s)=>{
let sc = s.target.scrollingElement.scrollTop;
console.log();
if(sc >=100){this.scroll=true}
else{this.scroll=false}
}
您的CSS
.level{
width: 100%;
height: 57px;
box-shadow: 0 0 5px 0 rgba(0, 0,0,0.7);
background: transparent;
display: flex;
position: fixed;
top: 0;
z-index: 5;
transition: .8s all ease;
}
.level-trans{
background: whitesmoke;
}
答案 4 :(得分:1)
以防万一我想捕捉一个没有滚动条的无法滚动的元素上的滚轮动作...
所以,我需要的是这个
@HostListener('mousewheel', ['$event'])
onMousewheel(event) {
console.log(event)
}
答案 5 :(得分:0)
@PierreDuc感谢您的回答。
如Improving scrolling performance with passive listeners中所述 有关MDN的部分:
您无需担心 被动 的价值 滚动事件。由于无法取消,因此事件监听器无法阻止 页面呈现。
就我而言,只需将 true 作为 window.addEventListener 函数的第三个参数传递,就可以简化您的答案。
答案 6 :(得分:0)
我不知道我是否遗漏了什么......因为我遇到了同样的问题(即使今天 [2021] 也无法在网上的任何地方找到任何答案)但后来只是尝试将“window”替换为“body” "而且它工作得很好(代码少了很多)。
代码片段(就我而言,添加到我的导航栏组件中):
@HostListener('body:scroll', ['$event'])
public onScrollingEvent(): void {
console.log('Currently scrolling');
this.navbarClass = ['nav', 'add-shadow'];
}
希望同一地点的其他人能找到这个,让他们的生活更轻松!