在我的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);
            }
        });
    }
}

Typescript相关问答推荐

如何在Jest中嘲笑location.back()方法调用进行Angular 组件测试?

Angular 过滤器形式基于某些条件的数组控制

如何正确修复TypScript 4.7到4.8升级中的TS 2345编译错误

角形标题大小写所有单词除外

打印脚本丢失函数的泛型上下文

使用axios在ngOnInit中初始化列表

来自类型脚本中可选对象的关联联合类型

类型脚本返回的类型包含无意义的泛型类型名称

如何解决类型T不能用于索引类型{ A:typeof A; B:typeof B;. }'

为什么有条件渲染会导致material 自动完成中出现奇怪的动画?

为什么我的一个合成函数不能推断类型?

tailwind css未被应用-react

如何使用泛型函数参数定义类型脚本函数

如何从接口中省略接口

如何通过转换器类继承使用多态将对象从一种类型转换为另一种类型

为什么TypeScrip假定{...省略类型,缺少类型,...选取类型,添加&>}为省略类型,缺少类型?

有没有一种方法可以提升对象的泛型级别,而对象的值是泛型函数?

打字:注解`是字符串`而不是`布尔`?

导航链接不触发自定义挂钩

JSX.Element';不可分配给类型';ReactNode';React功能HOC