在我的Angular 2应用中,当我向下滚动页面并单击页面底部的链接时,它确实会改变路由并将我带到下一页,但它不会滚动到页面顶部。因此,如果第一页很长,第二页内容很少,就会给人一种第二页缺乏内容的印象。因为只有当用户滚动到页面顶部时,内容才可见。

我可以滚动窗口到ngInit组件的页面顶部,但是,有没有更好的解决方案,可以自动处理我的应用程序中的所有路由?


当前回答

lastRoutePath?: string;

ngOnInit(): void {
  void this.router.events.forEach((event) => {
    if (event instanceof ActivationEnd) {
      if (this.lastRoutePath !== event.snapshot.routeConfig?.path) {
        window.scrollTo(0, 0);
      }
      this.lastRoutePath = event.snapshot.routeConfig?.path;
    }
  });
}

如果你停留在同一个页面上,它不会滚动到顶部,而只是改变了slug / id或其他东西

其他回答

对于每个正在寻找解决方案并阅读这篇文章的人。的

imports: [
  RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
  }),
  ...
]

并没有回答这个主题的问题。如果我们查看Angular的源代码,我们会看到一些有趣的行:

这个东西只对反向导航有用。其中一个解决方案可能是:

constructor(router: Router) {

    router.events
        .pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd))
        .subscribe(() => {
            this.document.querySelector('#top').scrollIntoView();
        });
}

这将查看每个导航到该id的div并滚动到它;

另一种方法是使用相同的逻辑,但在decorator或指令的帮助下,允许你选择何时何地滚动顶部;

最好的答案在Angular GitHub的讨论中(更改路由不会滚动到新页面的顶部)。

也许你只希望在根路由器的更改中(而不是在子路由器中)转到top。 因为你可以在f.e.选项卡中使用惰性加载加载路由)

app.component.html

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

全部归功于JoniJnm(原文)

你可以利用observable filter方法更简洁地写这个:

this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
      this.window.scrollTo(0, 0);
});

如果你在使用Angular Material 2 sidenav时遇到滚动到顶部的问题,这将有所帮助。窗口或文档主体不会有滚动条,因此您需要获得sidenav内容容器并滚动该元素,否则尝试将滚动窗口作为默认值。

this.router.events.filter(event => event instanceof NavigationEnd)
  .subscribe(() => {
      const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
      contentContainer.scrollTo(0, 0);
});

还有,Angular CDK v6。X现在有一个滚动包,可以帮助处理滚动。

window.scrollTo()在Angular 5中不适用,所以我使用了document.body.scrollTop:

this.router.events.subscribe((evt) => {
   if (evt instanceof NavigationEnd) {
      document.body.scrollTop = 0;
   }
});

您可以向组件添加AfterViewInit生命周期钩子。

ngAfterViewInit() {
   window.scrollTo(0, 0);
}