角5滚动到顶部的每个路线点击

我用的是角度5。我有一个仪表板,我有几个部分与小的内容和很少的部分与如此大的内容,我面临的问题时,改变路由器,而去顶部。每次我需要滚动到顶部。

我如何解决这个问题,以便当我改变路由器,我的观点总是留在顶部?

248656 次浏览

有一些解决方案,一定要检查它们全部:)


选择一:

每当一个新组件被实例化时,路由器插座都会发出 activate事件,所以我们可以使用 (activate)来滚动(例如)到顶部:

App.Component. html

<router-outlet (activate)="onActivate($event)"></router-outlet>

应用程序组件

onActivate(event) {
// window.scroll(0,0);


window.scroll({
top: 0,
left: 0,
behavior: 'smooth'
});


//or document.body.scrollTop = 0;
//or document.querySelector('body').scrollTo(0,0)
...
}

由于平滑滚动在 Safari 中没有很好的实现,例如,使用 这个解决方案来实现平滑滚动:

onActivate(event) {
let scrollToTop = window.setInterval(() => {
let pos = window.pageYOffset;
if (pos > 0) {
window.scrollTo(0, pos - 20); // how far to scroll on each step
} else {
window.clearInterval(scrollToTop);
}
}, 16);
}

如果您希望有选择性,例如不是每个组件都应该触发滚动,您可以在 if语句中检查它,如下所示:

onActivate(e) {
if (e.constructor.name)==="login"{ // for example
window.scroll(0,0);
}
}

选择二:

自 Angular6.1以来,我们也可以在急切加载的模块上使用 { scrollPositionRestoration: 'enabled' },它将应用于所有路由:

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

它也将做平滑滚动,已经。然而,这有不方便做它在每个路由。


选择三:

另一个解决方案是在路由器动画上做顶部滚动。在你想要滚动到顶部的每个转换中添加这个:

query(':enter, :leave', style({ position: 'fixed' }), { optional: true })

这里有一个解决方案,只有在第一次访问每个组件时才会滚动到 Component 的顶部(以防您需要对每个组件执行不同的操作) :

在每个组成部分:

export class MyComponent implements OnInit {


firstLoad: boolean = true;


...


ngOnInit() {


if(this.firstLoad) {
window.scroll(0,0);
this.firstLoad = false;
}
...
}

虽然@Vega 为你的问题提供了直接的答案,但也存在一些问题。它会破坏浏览器的后退/前进按钮。如果用户单击浏览器的“后退”或“前进”按钮,它们就会失去位置,并在顶部滚动。如果用户不得不向下滚动到一个链接,并决定单击回去,却发现滚动条已经被重置到顶部,那么这可能会给用户带来一点痛苦。

这是我对这个问题的解决办法。

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

我一直在寻找一个内置的解决方案,这个问题就像 AngularJS。但在此之前,这个解决方案为我工作,它很简单,并保留后退按钮的功能。

App.Component. html

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

应用程序组件

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

答案从 Zurfyx 原帖

编辑: 对于 Angular 6 + ,请使用 Nimesh Nishara Indimagedara 的回答提及:

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

原答案:

如果都失败了,那么在顶部创建一些空的 HTML 元素(例如: div)(或者想要的滚动到位置) ,在模板(或父模板)上使用 id = “ top”:

<div id="top"></div>

组成部分:

  ngAfterViewInit() {
// Hack: Scrolls to top of Page after page view initialized
let top = document.getElementById('top');
if (top !== null) {
top.scrollIntoView();
top = null;
}
}

对我来说,我只是加了

window.scroll(0,0);

ngOnInit()及其工作良好。

您只需要创建一个函数,其中包含调整您的屏幕滚动

比如说

window.scroll(0,0) OR window.scrollTo() by passing appropriate parameter.

ScrollTo (xpos,ypos)—— > 预期参数。

现在有一个内置的解决方案可在角度6.1与 scrollPositionRestoration选项。

请参阅 角2滚动到路线更改顶部上的 我的回答

试试这个:

应用程序组件

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Router, NavigationEnd} from '@angular/router';
import {filter} from 'rxjs/operators';
import {Subscription} from 'rxjs';


@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy {
subscription: Subscription;


constructor(private router: Router) {
}


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


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

export class AppComponent {
constructor(private router: Router) {
router.events.subscribe((val) => {
if (val instanceof NavigationEnd) {
window.scrollTo(0, 0);
}
});
}


}

如果你在角度6中遇到这个问题,你可以通过将参数 scrollPositionRestoration: 'enabled'添加到应用程序路由来解决它。的路由器模组:

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

组件: 订阅所有路由事件,而不是在模板中创建一个操作,并在 NavigationEnd b/c 上滚动,否则您将在错误导航或阻塞路由等情况下触发此操作。.这是一个确保万无一失的方法,可以知道如果一个路由成功导航到,然后顺利滚动。否则,什么都别做。

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {


router$: Subscription;


constructor(private router: Router) {}


ngOnInit() {
this.router$ = this.router.events.subscribe(next => this.onRouteUpdated(next));
}


ngOnDestroy() {
if (this.router$ != null) {
this.router$.unsubscribe();
}
}


private onRouteUpdated(event: any): void {
if (event instanceof NavigationEnd) {
this.smoothScrollTop();
}
}


private smoothScrollTop(): void {
const scrollToTop = window.setInterval(() => {
const pos: number = window.pageYOffset;
if (pos > 0) {
window.scrollTo(0, pos - 20); // how far to scroll on each step
} else {
window.clearInterval(scrollToTop);
}
}, 16);
}


}


超文本标示语言

<router-outlet></router-outlet>

试试这个

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

这个代码支持角度6 < =

来自 Angular Version 6 + 不需要使用 window.roll (0,0)

对于角形版本 6+,来自@< a href = “ https://v6.Angular.io/api/router/ExtraOptions”rel = “ noReferrer”> < strong > docs
表示配置路由器的选项。

interface ExtraOptions {
enableTracing?: boolean
useHash?: boolean
initialNavigation?: InitialNavigation
errorHandler?: ErrorHandler
preloadingStrategy?: any
onSameUrlNavigation?: 'reload' | 'ignore'
scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
anchorScrolling?: 'disabled' | 'enabled'
scrollOffset?: [number, number] | (() => [number, number])
paramsInheritanceStrategy?: 'emptyOnly' | 'always'
malformedUriErrorHandler?: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
urlUpdateStrategy?: 'deferred' | 'eager'
relativeLinkResolution?: 'legacy' | 'corrected'
}

一个人可以使用 scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'

例如:

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

如果需要手动控制滚动,不需要使用 window.scroll(0,0) 取而代之的是从角 V6通用软件包引入了 强 > ViewPortScoller

abstract class ViewportScroller {
static ngInjectableDef: defineInjectable({ providedIn: 'root', factory: () => new BrowserViewportScroller(inject(DOCUMENT), window) })
abstract setOffset(offset: [number, number] | (() => [number, number])): void
abstract getScrollPosition(): [number, number]
abstract scrollToPosition(position: [number, number]): void
abstract scrollToAnchor(anchor: string): void
abstract setHistoryScrollRestoration(scrollRestoration: 'auto' | 'manual'): void
}

用法很简单 例如:

import { Router } from '@angular/router';
import {  ViewportScroller } from '@angular/common'; //import
export class RouteService {


private applicationInitialRoutes: Routes;
constructor(
private router: Router;
private viewPortScroller: ViewportScroller//inject
)
{
this.router.events.pipe(
filter(event => event instanceof NavigationEnd))
.subscribe(() => this.viewPortScroller.scrollToPosition([0, 0]));
}

角度6.1及以后:

您可以使用 角度6.1 + 中提供的 内置的溶液和选项 scrollPositionRestoration: 'enabled'来实现同样的功能。

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

角度6.0及更早版本:

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

注: 预期的行为是,当您导航回到页面时,它应该保持向下滚动到单击链接时的相同位置,但是当到达每个页面时,它应该滚动到顶部。

如果您使用的 mat-sidenav 给路由器插座一个 id (如果您有父和子路由器插座) ,并在其中使用激活功能 <router-outlet id="main-content" (activate)="onActivate($event)"> 并使用这个“ mat-sidenav-content”查询选择器滚动顶部 OnActivate (event){ QuerySelector (“ mat-sidenav-content”) . scrollTo (0,0) ; }

加上

window.scrollTo({ top: 0 });

ngOnInit()

对于一些人谁正在寻找滚动函数只需添加函数和调用,当需要的时候

scrollbarTop(){


window.scroll(0,0);
}

由于某种原因,上面的方法都不适合我:/,所以我在 app.component.html的 top 元素中添加了一个元素 ref,在 router-outlet中添加了 (activate)=onNavigate($event)

<!--app.component.html-->
<div #topScrollAnchor></div>
<app-navbar></app-navbar>
<router-outlet (activate)="onNavigate($event)"></router-outlet>

然后,我将子文件添加到 app.Component. ts 文件中,使其成为 ElementRef类型,并让它在激活路由器插座时滚动到该文件。

export class AppComponent  {
@ViewChild('topScrollAnchor') topScroll: ElementRef;


onNavigate(event): any {
this.topScroll.nativeElement.scrollIntoView({ behavior: 'smooth' });
}
}

这是 Stackblitz的密码

对我有效的解决办法是:

document.getElementsByClassName('layout-content')[0].scrollTo(0, 0);

它的工作角度是8,9和10。

只需在 app.module.ts文件中添加以下代码行:

RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled' //scroll to the top
})

我使用角度11.1.4,它对我很有用

加就是了

 ngAfterViewInit() {
window.scroll(0,0)
}
<p class="text-center" (click)="scrollToTop()"> Back to top
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-up-short" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 12a.5.5 0 0 0 .5-.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 .5.5z"/>
</svg>
</p>




scrollToTop(): void {
window.scroll(0, 0);
}