Nav*_*med 246 typescript angular2-directives angular2-template angular2-routing angular
在我的Angular 2应用程序中,当我向下滚动页面并单击页面底部的链接时,它确实会更改路径并将我带到下一页但它不会滚动到页面顶部.结果,如果第一页很长而第二页的内容很少,则给人的印象是第二页缺少内容.由于只有当用户滚动到页面顶部时内容才可见.
我可以在组件的ngInit中将窗口滚动到页面顶部但是,有没有更好的解决方案可以自动处理我的应用程序中的所有路径?
Gui*_*les 343
您可以在主要组件上注册路线更改侦听器,并在路线更改时滚动到顶部.
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)
});
}
}
Run Code Online (Sandbox Code Playgroud)
Fer*_*ria 289
Angular 6.1及更高版本:
Angular 6.1(发布于2018-07-25)通过名为"路由器滚动位置恢复"的功能增加了内置支持来处理此问题.如官方Angular博客中所述,您只需在路由器配置中启用此功能,如下所示:
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
Run Code Online (Sandbox Code Playgroud)
此外,该博客指出"预计这将成为未来主要版本的默认版本",因此很可能从Angular 7开始,您不需要在代码中做任何事情,这只会起作用开箱即用.
Angular 6.0及更早版本:
虽然@ GuilhermeMeireles的优秀答案修复了原始问题,但它引入了一个新问题,通过打破您向后或向前导航时的正常行为(使用浏览器按钮或通过代码中的位置).预期的行为是,当您导航回页面时,它应该保持向下滚动到您单击链接时的相同位置,但是当到达每个页面时滚动到顶部显然会打破此期望.
下面的代码扩展了逻辑,通过订阅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);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
Abd*_*fay 56
从Angular 6.1开始,您现在可以避免麻烦并将extraOptions
其RouterModule.forRoot()
作为第二个参数传递给您,并且可以指定scrollPositionRestoration: enabled
告知Angular在路径更改时滚动到顶部.
默认情况下,您会在app-routing.module.ts
以下位置找到:
const routes: Routes = [
{
path: '...'
component: ...
},
...
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled', // Add options right here
})
],
exports: [RouterModule]
})
export class AppRoutingModule { }
Run Code Online (Sandbox Code Playgroud)
mtp*_*ltz 30
您可以通过利用可观察的filter
方法更简洁地编写这个:
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
this.window.scrollTo(0, 0);
});
Run Code Online (Sandbox Code Playgroud)
如果您在使用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);
});
Run Code Online (Sandbox Code Playgroud)
此外,Angular CDK v6.x 现在有一个滚动包,可能有助于处理滚动.
Rap*_*tor 16
如果您有服务器端呈现,则应注意不要windows
在服务器上运行代码,其中该变量不存在.这会导致代码破坏.
export class AppComponent implements OnInit {
routerSubscription: Subscription;
constructor(private router: Router,
@Inject(PLATFORM_ID) private platformId: any) {}
ngOnInit() {
if (isPlatformBrowser(this.platformId)) {
this.routerSubscription = this.router.events
.filter(event => event instanceof NavigationEnd)
.subscribe(event => {
window.scrollTo(0, 0);
});
}
}
ngOnDestroy() {
this.routerSubscription.unsubscribe();
}
}
Run Code Online (Sandbox Code Playgroud)
isPlatformBrowser
是一个函数,用于检查应用程序呈现的当前平台是否是浏览器.我们给它注射platformId
.
它也可以检查变量是否存在windows
,是安全的,如下所示:
if (typeof window != 'undefined')
Run Code Online (Sandbox Code Playgroud)
小智 12
只需点击操作即可轻松完成
在你的主要组件html中引用#scrollContainer
<div class="main-container" #scrollContainer>
<router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
</div>
Run Code Online (Sandbox Code Playgroud)
在主要组件.ts
onActivate(e, scrollContainer) {
scrollContainer.scrollTop = 0;
}
Run Code Online (Sandbox Code Playgroud)
zur*_*fyx 11
最好的答案在于Angular GitHub讨论(更改路线不会在新页面中滚动到顶部).
也许你只想在根路由器更改中转到顶部(不是在子节点中,因为你可以在一个tabset中加载延迟加载的路由)
app.component.html
<router-outlet (deactivate)="onDeactivate()"></router-outlet>
Run Code Online (Sandbox Code Playgroud)
app.component.ts
onDeactivate() {
document.body.scrollTop = 0;
// Alternatively, you can scroll to top by using this other call:
// window.scrollTo(0, 0)
}
Run Code Online (Sandbox Code Playgroud)
您可以将AfterViewInit生命周期钩子添加到组件中.
ngAfterViewInit() {
window.scrollTo(0, 0);
}
Run Code Online (Sandbox Code Playgroud)
小智 6
从Angular 6.1开始,路由器提供了一个名为的配置选项scrollPositionRestoration
,旨在满足这种情况。
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled'
}),
...
]
Run Code Online (Sandbox Code Playgroud)
除了@Guilherme Meireles提供的完美答案(如下所示)之外,您还可以通过添加平滑滚动来调整您的实现,如下所示
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)
});
}
}
Run Code Online (Sandbox Code Playgroud)
然后添加下面的代码段
html {
scroll-behavior: smooth;
}
Run Code Online (Sandbox Code Playgroud)
到你的styles.css
Angular最近引入了一项新功能,内部的角路由模块进行如下更改
@NgModule({
imports: [RouterModule.forRoot(routes,{
scrollPositionRestoration: 'top'
})],
Run Code Online (Sandbox Code Playgroud)
这是我想出的解决方案。我将 LocationStrategy 与 Router 事件配对。使用 LocationStrategy 设置一个布尔值以了解用户当前何时遍历浏览器历史记录。这样,我就不必存储一堆 URL 和 y-scroll 数据(无论如何都不能很好地工作,因为每个数据都是基于 URL 替换的)。这也解决了当用户决定按住浏览器上的后退或前进按钮并后退或前进多个页面而不是一个页面时的边缘情况。
PS 我只在最新版本的 IE、Chrome、FireFox、Safari 和 Opera 上进行了测试(截至本文)。
希望这可以帮助。
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;
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
122711 次 |
最近记录: |