Angular 2 在 Route Change 上滚动到顶部 [英] Angular 2 Scroll to top on Route Change

查看:24
本文介绍了Angular 2 在 Route Change 上滚动到顶部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Angular 2 应用程序中,当我向下滚动页面并单击页面底部的链接时,它会更改路线并将我带到下一页,但它不会滚动到页面顶部.结果,如果第一页很长而第二页内容很少,就会给人一种第二页内容不足的印象.因为内容只有在用户滚动到页面顶部时才可见.

In my Angular 2 app when I scroll down a page and click the link at the bottom of the page, it does change the route and takes me to the next page but it doesn't scroll to the top of the page. As a result, if the first page is lengthy and 2nd page has few contents, it gives an impression that the 2nd page lacks the contents. Since the contents are visible only if a user scrolls to the top of the page.

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

I can scroll the window to the top of the page in ngInit of the component but, is there any better solution that can automatically handle all routes in my app?

推荐答案

Angular 6.1 及更高版本:

Angular 6.1(于 2018 年 7 月 25 日发布)通过名为路由器滚动位置恢复"的功能添加了用于处理此问题的内置支持.如官方Angular 博客,你只需要像这样在路由器配置中启用它:

Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:

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

此外,该博客声明预计这将成为未来主要版本中的默认设置".到目前为止,这还没有发生(从 Angular 11.0 开始),但最终您将不需要在代码中做任何事情,这将直接开箱即用.

Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 11.0), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.

您可以在官方文档中查看有关此功能以及如何自定义此行为的更多详细信息.

Angular 6.0 及更早版本:

虽然@GuilhermeMeireles 的出色回答解决了最初的问题,但它引入了一个新问题,它打破了您在向后或向前导航(使用浏览器按钮或通过代码中的位置)时所期望的正常行为.预期的行为是,当您导航回该页面时,它应该保持向下滚动到与您点击链接时相同的位置,但在到达每个页面时滚动到顶部显然打破了这一预期.

While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). The expected behavior is that when you navigate back to the page, it should remain scrolled down to the same location it was when you clicked on the link, but scrolling to the top when arriving at every page obviously breaks this expectation.

下面的代码通过订阅 Location 的 PopStateEvent 序列并跳过滚动到顶部逻辑(如果新到达的页面是此类事件的结果)来扩展检测这种导航的逻辑.

The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.

如果您返回的页面足够长以覆盖整个视口,滚动位置会自动恢复,但正如@JordanNelson 正确指出的那样,如果页面较短,您需要跟踪原始 y 滚动位置并在您返回页面时明确恢复它.代码的更新版本也涵盖了这种情况,始终显式恢复滚动位置.

If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.

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);
            }
        });
    }
}

这篇关于Angular 2 在 Route Change 上滚动到顶部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆