我对这里的大多数人采取了不同的方法。停止滚动最简单的方法是利用 css 将溢出设置为隐藏。
考虑到这一点,我创建了一个指令,它利用角度 @HostListener 来监听滚动事件。一旦附加指令的元素的底部滚动到视图中,我们就禁用 body 元素上的 overflow-y。
首先我们注入我们需要的服务
constructor(private render: Renderer2, private container: ViewContainerRef) {}
我们将利用 Renderer2 将样式应用到 body 元素,并且我们需要对该指令的 ViewContainer 的引用,以了解何时应用指令的对象的底部区域位于视口内。
我们设置 @HostListener 来完成此操作:
@HostListener("window:scroll")
scrollEvent() {
const bounds = this.container.element.nativeElement.getBoundingClientRect();
if (bounds.bottom <= window.innerHeight) {
this.render.setStyle(document.body, "overflowY", "hidden");
}
}
这实际上可以满足我们的需要。从这里您可以启动您需要的任何其他逻辑,例如动画转换等。
扩展示例
我在指令中添加了更多细节,例如用于解除滚动冻结的 EventEmitter 的输入绑定,以及仅触发一次的标志。完整的指令列表如下:
import { Directive, HostListener, Renderer2, ViewContainerRef, EventEmitter, Input, OnInit } from "@angular/core";
@Directive({
selector: "[appScroll]"
})
export class ScrollDirective implements OnInit {
@Input() fireOnce: boolean;
@Input() enableScroll: EventEmitter<any>;
hasFired: boolean;
@HostListener("window:scroll")
scrollEvent() {
const bounds = this.container.element.nativeElement.getBoundingClientRect();
if (bounds.bottom <= window.innerHeight && !this.hasFired) {
this.render.setStyle(document.body, "overflowY", "hidden");
this.hasFired = this.fireOnce;
}
}
constructor(private render: Renderer2, private container: ViewContainerRef) {
this.hasFired = false;
}
ngOnInit() {
if (this.enableScroll) {
this.enableScroll.subscribe(r => this.removeNoSCrollClass());
}
}
removeNoSCrollClass() {
this.render.removeStyle(document.body, "overflowY");
}
}
您可以在此处找到 stackblitz 示例:https://stackblitz.com/edit/angular-ivy-64dpad