在我的Angular 2应用程序中,当我向下滚动页面并单击页面底部的链接时,它确实会更改路径并将我带到下一页,但不会滚动到页面顶部.如果第二页的内容太少,那么第二页就会给人留下很长的印象.因为只有当用户滚动到页面顶部时,内容才可见.
我可以在组件的ngInit中将窗口滚动到页面顶部,但是,有没有更好的解决方案可以自动处理我应用程序中的所有路由?
在我的Angular 2应用程序中,当我向下滚动页面并单击页面底部的链接时,它确实会更改路径并将我带到下一页,但不会滚动到页面顶部.如果第二页的内容太少,那么第二页就会给人留下很长的印象.因为只有当用户滚动到页面顶部时,内容才可见.
我可以在组件的ngInit中将窗口滚动到页面顶部,但是,有没有更好的解决方案可以自动处理我应用程序中的所有路由?
Angular 6.1 and later:
Angular 6.1(于2018年7月25日发布)通过一个名为"路由滚动位置恢复"的功能添加了内置支持来处理此问题.如官方Angular blog中所述,您只需在路由配置中启用以下功能:
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
此外,该博客称,"预计这将成为future 主要版本的默认设置".到目前为止,这种情况还没有发生(从Angular 11.0开始),但最终您将不需要在代码中执行任何操作,这将直接正常工作.
您可以在the official docs中看到有关此功能以及如何自定义此行为的更多详细信息.
Angular 6.0 and earlier:
尽管@guillermeireles的优秀答案修复了原来的问题,但它引入了一个新的问题,打破了您在向后或向前导航(使用浏览器按钮或通过代码中的位置)时预期的正常行为.预期的行为是,当您导航回页面时,它应该保持向下滚动到与您单击链接时相同的位置,但当到达每个页面时滚动到顶部显然打破了这一预期.
下面的代码通过订阅Location的PopStateEvent序列,并在新到达的页面是此类事件的结果时跳过滚动到顶部逻辑,扩展了检测此类导航的逻辑.
如果返回的页面足够长,可以覆盖整个视口,滚动位置会自动恢复,但正如@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);
}
});
}
}