在我的Angular 2应用程序中,当我向下滚动一个页面并点击页面底部的链接时,它会改变路径并带我进入下一个页面,但它不会滚动到页面顶部。因此,如果第一页很长,而第二页的内容很少,就会给人一种第二页缺少内容的印象。因为只有当用户滚动到页面顶部时,内容才可见。
我可以在组件的ngInit中滚动窗口到页面顶部但是,有没有更好的解决方案可以自动处理我的应用程序中的所有路线?
Angular 6.1及更高版本:
Angular 6.1(发布于2018-07-25)通过一个名为“路由器滚动位置恢复”的功能增加了内置支持来处理这个问题。正如Angular官方博客中所描述的,您只需在路由器配置中启用此功能,如下所示:
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
此外,博客还说“预计这将成为未来主要版本的默认设置”。到目前为止,这还没有发生(从Angular 11.0开始),但最终您将不需要在代码中做任何事情,并且这将直接正确地工作。
您可以在官方文档中看到更多关于此特性的详细信息以及如何自定义此行为。
Angular 6.0及更早版本:
虽然@guilhermeireles的出色回答解决了原来的问题,但它引入了一个新的问题,打破了您在往后或向前导航时预期的正常行为(使用浏览器按钮或通过代码中的位置)。预期的行为是,当您导航回页面时,它应该保持向下滚动到与您单击链接时相同的位置,但到达每个页面时滚动到顶部显然打破了这种预期。
下面的代码通过订阅Location的PopStateEvent序列并跳过scroll-to-top逻辑来检测这种导航,如果新到达的页面是这样一个事件的结果的话。
如果返回的页面足够长,可以覆盖整个视区,滚动位置会自动恢复,但正如@Jordannelson正确指出的,如果页面较短,则需要跟踪原始的y滚动位置,并在返回页面时显式恢复。代码的更新版本也涵盖了这种情况,它总是显式地恢复滚动位置。
import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { Location, PopStateEvent } from "@angular/common";
@Component({
selector: 'my-app',
template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
private lastPoppedUrl: string;
private yScrollStack: number[] = [];
constructor(private router: Router, private location: Location) { }
ngOnInit() {
this.location.subscribe((ev:PopStateEvent) => {
this.lastPoppedUrl = ev.url;
});
this.router.events.subscribe((ev:any) => {
if (ev instanceof NavigationStart) {
if (ev.url != this.lastPoppedUrl)
this.yScrollStack.push(window.scrollY);
} else if (ev instanceof NavigationEnd) {
if (ev.url == this.lastPoppedUrl) {
this.lastPoppedUrl = undefined;
window.scrollTo(0, this.yScrollStack.pop());
} else
window.scrollTo(0, 0);
}
});
}
}