Angular: 更改路线不会滚动到新页面的顶部

创建于 2016-03-28  ·  103评论  ·  资料来源: angular/angular

当从一条路线导航到另一条路线然后向下滚动一点并导航回上一条路线时,页面将保持在相同的滚动位置。

当前行为

从一个视图导航到另一个视图,然后向下滚动一点并导航回上一个视图。 页面保持在相同的滚动位置。

预期/期望行为

当导航回另一条路线时,页面应滚动到顶部。

router feature high google obvious

最有用的评论

也许您只想在根路由器更改中转到顶部(而不是在子路由器中,因为您可以在 fe tabset 中使用延迟加载加载路由)

另一种解决方法:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    document.body.scrollTop = 0;
}

所有103条评论

重复#6595?

重复#6595?

我不这么认为。

6946 显示了一种解决方法

预期/期望行为

当导航回另一条路线时,页面应滚动到顶部。

这对我来说不是预期的行为。 我的预期行为是:

当导航回另一条路线时,页面应该滚动到前进之前的位置。 这是当前在所有浏览器中在普通页面(不是 SPA)之间导航时实现的行为。 但是我从未在 angular1 路由器的任何实现中看到过这种行为。

当您向下滚动某些列表时,单击列表项以查看详细信息页面,向下滚动详细信息,然后单击浏览器Back按钮,却无法看到与以前完全相同的状态的列表页面,这非常烦人。

  • 如果它根本不滚动:您只会在列表页面上随机滚动位置。
  • 如果它滚动到顶部:它会更好,但您最终总是位于列表页面的顶部,而在任何“正常”站点(不是 SPA)中,您最终会处于您在进入详细信息页面之前所在的滚动位置。

例如,github 正确实现了这一点:打开问题列表并向下滚动,然后打开任何问题详细信息,然后单击Back浏览器按钮。 您将最终处于与打开问题详细信息页面之前完全相同的滚动位置。

如果 angular2 路由器能够做到这一点,那将是非常酷的。 这真的是我从未在任何其他路由器中见过的杀手级功能。

编辑
现在有针对此行为的专门问题https://github.com/angular/angular/issues/10929

有一些属性或参数来改变这个默认的滚动行为可能会更好?

在 RC.4 中是否有推荐的滚动到顶部的方法? #6946 中建议的解决方法不再有效。

@andyrue我不认为这会被推荐,但我在 #6946 上发布了更新

在我的情况下, window.scrollTo(0, 0)技巧不起作用,因为我实际上需要滚动到溢出的路由器插座的顶部。 如果您有类似的问题,这就是我作为解决方法所做的:

@Component({
  template: '<router-outlet (activate)="onActivate($event, outlet)" #outlet></router-outlet>,
})
export class MyParentComponent {
  onActivate(e, outlet){
    outlet.scrollTop = 0;
  }
}

有什么解决办法吗? 建议的解决方案都不起作用。
这似乎对我有用——持续多久,不确定:

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

@Ariix不会在每次更改检测运行后滚动?

@Cortopy是的,是的。 所以还在找

任何更新或里程碑?

这事有进一步更新吗? 当您向下滚动某些列表时很烦人,单击列表项以查看详细信息(在另一条路线上),您必须向上滚动。 如果下一个详细信息页面的长度很小并且列表页面很长并且您偶然单击了列表中的最后一项。 这会给人一种在详细信息页面上没有任何内容的印象(因为用户必须向上滚动才能查看内容)。

@zoechi我相信评论是关于带有哈希的 URL,就我而言,我没有任何哈希:

列表页面有一个网址:
/列表

详细信息页面有一个网址:
/详细信息/123

@naveedahmed1你仍然可以打电话给scrollIntoView()scrollTop=0

@zoechi - 你能分享完整的代码吗? 我有父子场景,其中子路由正在改变

我的工作涉及 ElementRef 类。

  constructor(
    private route: ActivatedRoute,
    private service: GuideService,
    private router: Router,
    private element: ElementRef
  ) {
    this.scrollUp = this.router.events.subscribe((path) => {
      element.nativeElement.scrollIntoView();
    });
  }

这个怎么样?

import { Component, OnInit} from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    moduleId: module.id,
    selector: 'app',
    templateUrl: './app.component.html'
})

export class AppComponent implements OnInit {
    constructor(private router: Router) {}

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }

            var scrollToTop = window.setInterval(function () {
                var pos = window.pageYOffset;
                if (pos > 0) {
                    window.scrollTo(0, pos - 20); // how far to scroll on each step
                } else {
                    window.clearInterval(scrollToTop);
                }
            }, 16); // how fast to scroll (this equals roughly 60 fps)
        });
    }
}
    router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {
        window.scroll(0, 0);
    });

这似乎记住了滚动位置(在 Chrome 和 Firefox 中,但不是 IE),但我不知道为什么。

@SmaugTheGreat是的,确实有效! 但是它怎么可能记住最后的滚动位置呢?

很奇怪,当使用@SmaugTheGreat解决方案时,即 window.scroll(0, 0); 它记住滚动位置。
但是在 window.setInterval 中使用 window.scroll 时,它不记得滚动位置。

为什么 NavigationEnd 不包含路线的参数、查询参数等? 只有字符串?

上面的 Smaugs 解决方案和 stackoverflow 上的 Guilherme Meireles 的混合对我来说很有效。 还要取消订阅 ngOnDestroy 以避免泄漏。

import { Component } from '@angular/core'; 
import { Router, NavigationEnd } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx';

@Component({
    moduleId: module.id, 
    selector: ‘my-app’,
    template: `<router-outlet></router-outlet>`
})

export class AppComponent {
    routerSubscription: Subscription;

    constructor(private router: Router) {}

    ngOnInit() {
        this.routerSubscription = this.router.events
            .filter(event => event instanceof NavigationEnd)
            .subscribe(event => {
                document.body.scrollTop = 0;
            });
    }

    ngOnDestroy() {
        this.routerSubscription.unsubscribe();
    }
}

使用“ng2-page-scroll”模块。 作为快速响应,我发布了我的一个组件。 这个对我有用。

从“@angular/core”导入 {Component, OnInit, Inject };
从'@angular/router' 导入 {Router, Route, NavigationEnd};
从“../app.service”导入{ AppSharedService};
从“@angular/platform-b​​rowser”导入{文档};
从'rxjs/Rx'导入{订阅};
从 'ng2-page-scroll' 导入 { PageScrollService, PageScrollInstance };

@零件({
选择器:'应用程序资源',
templateUrl: './resources.component.html',
styleUrls: ['./resources.component.scss']
})
导出类资源组件{

routerSubscription:订阅;

构造函数(私有路由器:路由器,私有 SharedService:AppSharedService,私有 pageScrollService:PageScrollService,@Inject(DOCUMENT)私有文档:任何,){
让 pageScrollInstance: PageScrollInstance = PageScrollInstance.simpleInstance(this.document, '#app-give');
this.pageScrollService.start(pageScrollInstance);

}

}

@shanehickeylk
我相信您只需要取消订阅,因为您专门将订阅保存到一个变量中。

如果你只是直接调用 router.events..... .subscribe() ,则没有订阅取消订阅。

更新:是的,你这样做:) 对不起,伙计们

@spock123
我相信即使没有分配给变量,订阅仍然是“活跃的”。 这就是 angular 知道事件已被触发的方式。 将它分配给一个变量的原因是它可以在以后访问和取消订阅。

这是 Brian Love 的一篇好文章,他在其中详细介绍了该主题:
http://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/

好的,谢谢...需要尽快重写一些生产,😎😎

也许您只想在根路由器更改中转到顶部(而不是在子路由器中,因为您可以在 fe tabset 中使用延迟加载加载路由)

另一种解决方法:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    document.body.scrollTop = 0;
}

只想报告说,每当我使用路由解析器时,我都会看到这个问题。 看起来它与组件在路由器中被销毁/加载的时间有关。 当我使用解析器时,似乎组件加载真的很快,太快了,就像路由器出口从来没有真正空过或其他东西一样,所以滚动位置从以前的组件中保存下来。 然而,在我所有的其他路线/组件上,这不是问题

我通过在 ui-view 中添加 autoscroll="true" 解决了这个问题

josh81,你说的是角度1,不是角度2

@JoniJnm也许使用渲染器会更好?

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

import { Component, Renderer } from '@angular/core';

```导出类 AppComponent {

构造函数(私有渲染器:渲染器){
}

onDeactivate() {
this.renderer.setElementProperty(document.body, "scrollTop", 0);
}
}
``

我将此添加到我的app.component::ngOnInit以解决在路由后由于内容位于 sidenav 内容容器而导致窗口或文档正文上的本机滚动不起作用的滚动问题。 以防在 beta.4 之前这可以暂时帮助任何人。

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

我创建了一个处理这个的小服务:

教程

来源

@kormic使用Renderer是个好主意! 但是, Renderer已被弃用,因此现在应该使用Renderer2 。 在Renderer2也将setElementProperty()更改为setProperty() Renderer2

我将其与@kormic@mtpultz的解决方法结合起来,这对我来说似乎很有效:

    this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
      this.renderer.setProperty(document.body, 'scrollTop', 0);
    });

@Splaktar我有一个有角度的通用应用程序。 如何避免服务器异常。
3 种方式有效,但我有一条服务器消息,:

window.scrollTo(0,0); //未定义窗口。
this.element.nativeElement.scrollIntoView(false); //scrollIntoView 未定义
this.renderer.setProperty(document.body,'scrollTop',0); //文档未定义

经过一个小时的努力终于找到了服务端渲染的解决方案

if (isPlatformBrowser(this.platformId)) {
                var scrollingElement = this.document.scrollingElement || this.document.documentElement;
                this.renderer.setProperty(scrollingElement ,'scrollTop',0);
            }

仅供参考,任何关心这一点的人可能也关心在导航“返回”时保留先前视图的滚动位置。 那是在一个单独的问题 #10929 中。

我的问题是,这与#hash 锚点如何结合使用,这些锚点在 Angular 中经过 10 次路由器迭代后不支持开箱即用?

  1. 当我点击一个链接时,它应该滚动到顶部。
  2. 如果我点击一个链接并且它有一个#,它应该转到那个页面并滚动到它,或者如果它是同一个页面向下滚动到它。
  3. 如果我向后或向前击球,它应该回到我所在的位置。

这并不难。 我以为这在 1992 年就已经解决了。请谷歌的某个人站起来敲门。 这需要在昨天修复。 因为 Lynx 能够做到,我不应该仅仅为了做每个浏览器的事情而编写 hacks。

app.component.ts ,添加如下代码
this.router.events.filter(event => event instanceof NavigationEnd).subscribe((e: NavigationEnd) => {
document.body.scrollTop = 0;
});

除其他外,页面上的# 符号不能正常工作。这需要由 Angular 团队根据上述要求在根代码中正确修复。

这确实需要成为 SPA 中的预期行为。 我们正在为我们的生产应用程序尝试一种解决方法,它确实应该是开箱即用的解决方案。

我同意之前的大部分评论:由于我的应用程序尚未投入生产,因此我暂缓希望这将在不需要任何变通方法的情况下实施。

自动滚动不再在 Firefox 中工作:-/
55.0.1(64 位)

Chrome 按预期工作。

这对我有用
let number = window.scrollY || window.pageYOffset || document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0)

我的团队一直在使用angular 团队在 angular.io<body>的顶部: <div id="top-of-page"></div>

我刚用
this.router.navigate(['myNextPage']).then(() => { window.scrollTo(0, 0) });

它奏效了。

再说一次,这不是它应该做的。

如果您访问一个常规的旧网站并点击后退按钮,它会返回并保留您单击的页面上的确切位置,因此您将回到上次离开的位置。

Angular 需要内置它并且它需要正常工作。 没有黑客攻击,没有提供对功能的错误估计。 真正的交易完全按照用户的预期自动运行。

只需将其添加到您的主要组件中

constructor(private router: Router) {
    this.router.events.subscribe(
      () => window.scrollTo(0, 0)
    );
  }

这对我有用:

<router-outlet (deactivate)="onDeactivate()"></router-outlet>
onDeactivate() {
    window.scrollTo(0, 0);
}

@JohnGalt1717您在旧网站上看到的内容由浏览器处理。 对于像 angular 这样的框架来说,这是完全不同的。 angular 必须使用 javascript 来处理问题,这可能无法获得一致且干净的解决方案。 所有其他框架都有同样的问题。 解决这个问题的唯一简单方法是在切换路由时隐藏元素而不是销毁它们,然后浏览器会做恢复滚动位置的事情。

@crysislinux这实际上非常简单。 在他们拦截后退按钮并重新导航的历史缓冲区中,他们还需要存储滚动位置,当按下后退/前进时,它们会在 ngOnInit() 完成后滚动到该位置。

除了你不能在 ngOnInit 上完全做到这一点,因为不是所有的(比如异步)数据可能都被渲染了

因为 ngOnInit 允许异步(承诺),你可以。 如果开发人员没有做对,那不是你的问题,而是他们做错了。

我希望你们考虑恢复我在页面上消失的每个可滚动 div,在我横向旋转我的设备后,它们可能会异步加载数据,包括图像。

这没有什么微不足道的......我很惊讶到目前为止没有人想出一个插件。 你会立刻成名。 同时,只需滚动到顶部:-)

我从可用性方面带来的最佳解决方案(至少在 Chrome 中)是在我以这种方式进行前向导航的地方手动执行 window.scroll :

this.router.navigate(['/payment']).then(() => {
  window.scroll(0, 0); // should be here, in promise
});

在这种情况下,如果我向后导航,Chrome 会正确恢复滚动位置,如果我向前导航,则重置位置(但是,是的,您需要在任何地方手动执行此操作,或者使用某种自己的导航方法,未找到其他解决方案)。

只是广播@kormic的解决方案从@angular/core库中导入Renderer对象的解决方案,该对象由app.component.ts文件中的onDeactivate()函数触发,仍然适用于我的 Angular 4 项目,使用[email protected] 构建。

这对我有用:
https://stackoverflow.com/questions/39601026/angular-2-scroll-to-top-on-route-change

在您的组件中:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
    constructor(private router: Router) { }

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }
}

我升级到 Angular 5,但这些都没有用。 事实上,我的 DOM 调用似乎根本没有起作用(例如 window.scrollTo(0, 0) )。

简单的解决方案是在所需组件的 ngOnInit 中添加 window.scrollTo(0,0) 。
```javascript
ngOnInit() {
window.scrollTo(0, 0);
}

@ericmartinezr感谢您的更新。 我正在使用 Angular Material(特别是 MatSidenav),这就是调用 window 和 body 不起作用的原因。 (例如,它们不可滚动)。 一旦我在适当的 DOM 元素(例如.mat-sidenav-content )上调用它,一切都会起作用。 我只是假设元素bodywindow是可滚动的,因为它们是.mat-sidenav-content父元素。

当导航回另一条路线时,页面应该滚动到前进之前的位置。 这是当前在所有浏览器中在 > 普通页面(不是 SPA)之间导航时实现的行为。 但是我从未在 angular1 路由器的任何实现中看到过这种行为。

@xak2000提出了一个很好的观点,但我看到的行为是无论是“后退”操作还是导航到全新页面,滚动位置都会保持不变。 我可以保持后退动作的滚动位置,但似乎是导航到新页面的错误。

感谢@naveedahmed1 ; 它工作得很好

@bobrosoft滚动相同,当承诺解决是我的最佳解决方案时

此外,对于 chrome,它也适用于 safari

@naveedahmed1谢谢^_^

window.scrollTo() 可以工作,但是如果在任何 DOM 对象存在的地方使用通用会发生什么?

@marticrespi服务器上没有滚动位置的概念,因此只需将scrollTo代码包装在isPlatformBrowser支票中。

这是我的解决方案...

编辑:我应该提到这回答了如何在更改路线时将滚动条重置回顶部的问题。 此外,它还确保浏览器的后退和前进按钮不会损坏。 意思是,当您单击后退或前进时,滚动条会回到您最初离开页面时的位置。 此外,还有一个边缘情况,如果您单击并按住后退或前进浏览器按钮,一切正常,这与我目前看到的其他答案不同。 真的希望这会有所帮助...

      export class AppComponent implements OnInit {
      isPopState = false;

      constructor(private router: Router, private locStrat: LocationStrategy) { }

      ngOnInit(): void {
        this.locStrat.onPopState(() => {
          this.isPopState = true;
        });

        this.router.events.subscribe(event => {
          // Scroll to top if accessing a page, not via browser history stack
          if (event instanceof NavigationEnd && !this.isPopState) {
            window.scrollTo(0, 0);
            this.isPopState = false;
          }

          // Ensures that isPopState is reset
          if (event instanceof NavigationEnd) {
            this.isPopState = false;
          }
        });
      }
    }

@sal-vader 效果很好,谢谢

效果很好,谢谢;)

这在rc4中仍然被打破

我通过简单地添加解决了这个问题

constructor(private router: Router) { this.router.events.subscribe( () => window.scrollTo(0, 0) ); }
在 app.component.ts(我有顶级路由器插座)中,就是这样

上述解决方案在许多设备上都可以正常工作,但正如我检查的那样,它在移动设备上不起作用。 以下解决方案是我用来在不同类型的设备中解决此问题的方法。 起初我在 app.component 的构造函数中检查了移动设备

如果(isPlatformBrowser(this.platformId)){
如果(window.screen.width <= 1024){
this.mobile = 真;
}

然后在 ngOnInit

如果(isPlatformBrowser(this.platformId)){
this.routerSubscription = this.router.events
.filter(event => event instanceof NavigationEnd)
.订阅(事件 => {
如果(this.mobile){
const element = document.querySelector('#scrollId1');
element.scrollIntoView();
} 别的 {
window.scrollTo(0, 0);
}
});
}

您也可以在 ngOnInit 或构造函数中合并所有这些。
请注意,您应该将最上方 div 的 id 设置为 scrollId1 以适用于移动设备。

在我的情况下,上述解决方案不起作用,我检查了控制台,发现窗口的 scrollTo() 方法不起作用,所以我找到了另一个解决方案,而不是将用户带到位置 0,页面的 0 我使用了 scrollIntoView() 方法,将页面的顶部组件(在我的例子中为 app-website-nav)带入一个视图中,并且,它有效!!!! 现在,每次 URL 更改时,视图都会位于我的 app-website-nav 组件所在的页面顶部!
这里的代码,简单且有效:

import { Router, NavigationEnd } from '@angular/router';
private router: Router,

constructor(private router: Router)

ngOnInit()
   {
     this.router.events.subscribe((evt) => {
                 if (!(evt instanceof NavigationEnd)) {
                     return;
                 }
                 document.getElementsByTagName("app-website-nav")[0].scrollIntoView();
             });
   }

为了通过路由器更改平滑滚动,您可以使用

  constructor(private router: Router) {}

  ngOnInit() {
    this.router.events.subscribe(() =>
      window.scrollTo({
        top: 0,
        left: 0,
        behavior: 'smooth'
      })
    );
  }

@mkhan004很有趣,但我可以问一下, behavior不是浏览器原生的吗(https://www.w3schools.com/jsref/met_win_scrollto.asp)?

因此,您是否使用了一个特殊的 lib/polyfill 来覆盖window.scrollTo或其他东西?

@peterpeterparker这是本机浏览器行为。 忠告 - 不要使用 W3Schools,它以不精确或完全错误的信息而闻名。 最好使用MDN; 相关页面: https :

@mgol thx 👍

值得一提的是:IE 或 Edge 不支持behavior: 'smooth'

不过,当前版本的 Chrome 和 Firefox 似乎可以工作。

@MartinMa这是一个好点; 相关的 Can I Use 页面是https://caniuse.com/#feat =css-scroll-behavior

请注意,即使只是省略behavior: 'smooth'仍然会破坏 IE/Edge/Safari,因为它们不支持scrollTo的对象语法,只是位置语法: scrollTo(x, y) 。 为了支持 Chrome/Firefox 平滑滚动和其他非平滑滚动,您可以使用以下逻辑(具有所需的x / y值):

if ('scrollBehavior' in document.documentElement.style) {
  window.scrollTo({
    behavior: 'smooth',
    left: x,
    top: y,
  });
} else {
  window.scrollTo(x, y);
}

那么解决这个问题的最佳选择是什么?

关闭基于固定如上。

在 ngOnit 中使用window.scrollTo(0,0); 。 所以它应该是这样的
ngOnInit() { window.scrollTo(0,0); }

看看 Angular 6.1。 它已修复,可能在未来的版本中,它将是默认值

这是最好的解决方案!!!

从“@angular/core”导入{组件};
从“@angular/router”导入{路由器,导航结束};

@零件({
选择器:'sv-app',
模板: ' '
})
导出类 AppComponent {

构造函数(私有路由器:路由器){

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

}
}

一种解决方法是将其放在 application.run() 中 - 至少在旧版本的 Angular 中。 可能会帮助某人!

``
var 间隔 = setInterval(function() {
如果(document.readyState === '完成'){
$window.scrollTo(0, 0);
清除间隔(间隔);
}
}, 10);

@JamieFarrelly官方解决方案已在 angular 6.1 中发布

router: 实现滚动恢复服务 (#20030) (49c5234), closes #13636 #10929 #7791 #6595

@查看文档:

[编辑] 所以在你的情况下:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'top'
  })],
  exports: [RouterModule]
})

这不适用于 Angular Material <mat-sidenav-container fullscreen> ,我认为这是因为滚动容器现在是<mat-sidenav-content>而不是文档正文。 有没有办法解决这个问题?

@odahcam我正在使用 MatDrawerContainer 并且它与 ViewChild 一起工作

@ViewChild('scroll') myScrollContainer:MatDrawerContainer; 
this.myScrollContainer.scrollable.getElementRef().nativeElement.scrollTop= 0;

是的,我可以滚动容器,但是如何让路由器为我自动滚动它? (就像视口一样)

@odahcam

  <router-outlet (activate)="onActivate($event)"></router-outlet>
onActivate(event){
    this.myScrollContainer.scrollable.getElementRef().nativeElement.scrollTop= 0;
}

还是我误会了你?

实际上我正在使用类似的东西,但我认为路由器应该有一些可滚动的容器配置,因为当您启用scrollPositionRestoration: 'top'选项时它会尝试通过视口滚动,但它不起作用。

您的代码和我的一样完成这项工作,但我们俩都无法从为我们完成滚动工作的本机路由器功能中获利。 为此,我们需要告诉路由器使用我们自定义的可滚动容器而不是视口。

我注意到路由器使用了一个叫做ViewportScroller ,正如文档所说,如果你不想自定义滚动行为,你应该在你的模块或组件中注入那个人:

class AppModule {
 constructor(router: Router, viewportScroller: ViewportScroller, store: Store<AppState>) {
   router.events.pipe(filter(e => e instanceof Scroll), switchMap(e => {
     return store.pipe(first(), timeout(200), map(() => e));
   }).subscribe(e => {
     if (e.position) {
       viewportScroller.scrollToPosition(e.position);
     } else if (e.anchor) {
       viewportScroller.scrollToAnchor(e.anchor);
     } else {
       viewportScroller.scrollToPosition([0, 0]);
     }
   });
 }
}

这让我认为将全屏cdkContainer类的东西集成到路由器滚动恢复的唯一方法是实现我自己的ViewportScroller并更改 Angular 用于路由器注入我的注入令牌滚动条而不是默认值。

不幸的是,这件事的文档有点不存在,所以事情更加困难。

Angular 6.1 及更高版本:

RouterModule.forRoot(路由,{scrollPositionRestoration:'启用'})

@odahcam我已将您的评论与相关的 Angular Material 问题相关联: https :

@Splaktar好吧,已发布。

上面的 Smaugs 解决方案和 stackoverflow 上的 Guilherme Meireles 的混合对我来说很有效。 还要取消订阅 ngOnDestroy 以避免泄漏。

import { Component } from '@angular/core'; 
import { Router, NavigationEnd } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx';

@Component({
    moduleId: module.id, 
    selector: ‘my-app’,
    template: `<router-outlet></router-outlet>`
})

export class AppComponent {
    routerSubscription: Subscription;

    constructor(private router: Router) {}

    ngOnInit() {
        this.routerSubscription = this.router.events
            .filter(event => event instanceof NavigationEnd)
            .subscribe(event => {
                document.body.scrollTop = 0;
            });
    }

    ngOnDestroy() {
        this.routerSubscription.unsubscribe();
    }
}

对于那些不能在 Observable 上使用 filter(), map() 等操作符的人添加这个:

import { filter, map } from 'rxjs/operators';

Angular 6.1 及更高版本:

RouterModule.forRoot(路由,{scrollPositionRestoration:'启用'})

对于寻求简单而干净的解决方案来保持向后导航的滚动位置并在向前导航时滚动到顶部的其他人来说,这就是解决方案。 未来将成为默认的 Angular 行为(由 angular 规范描述:https://angular.io/api/router/ExtraOptions)

Angular 6.1 及更高版本:
RouterModule.forRoot(路由,{scrollPositionRestoration:'启用'})

对于寻求简单而干净的解决方案来保持向后导航的滚动位置并在向前导航时滚动到顶部的其他人来说,这就是解决方案。 未来将成为默认的 Angular 行为(由 angular 规范描述:https://angular.io/api/router/ExtraOptions)

我想加一个半拇指! 😅

如果您有以下ExtraOptions

// ...
const routerOptions: ExtraOptions = {
  useHash: false,
  anchorScrolling: 'enabled',
  scrollPositionRestoration: 'enabled'
};
// ...

为了启用锚链接,它总是在顶部,即使锚在页面底部。

但如果你不使用锚导航,这是一个很棒的修复! 😉

由于不活动,此问题已自动锁定。
如果您遇到类似或相关的问题,请提交新问题。

阅读有关我们的自动对话锁定政策的更多信息。

_此操作已由机器人自动执行。_

此页面是否有帮助?
0 / 5 - 0 等级