在我的Angular 2应用中,当我向下滚动页面并单击页面底部的链接时,它确实会改变路由并将我带到下一页,但它不会滚动到页面顶部。因此,如果第一页很长,第二页内容很少,就会给人一种第二页缺乏内容的印象。因为只有当用户滚动到页面顶部时,内容才可见。
我可以滚动窗口到ngInit组件的页面顶部,但是,有没有更好的解决方案,可以自动处理我的应用程序中的所有路由?
在我的Angular 2应用中,当我向下滚动页面并单击页面底部的链接时,它确实会改变路由并将我带到下一页,但它不会滚动到页面顶部。因此,如果第一页很长,第二页内容很少,就会给人一种第二页缺乏内容的印象。因为只有当用户滚动到页面顶部时,内容才可见。
我可以滚动窗口到ngInit组件的页面顶部,但是,有没有更好的解决方案,可以自动处理我的应用程序中的所有路由?
当前回答
如果您使用服务器端呈现,则应该注意不要在服务器上使用窗口运行代码,因为服务器上不存在该变量。这将导致代码被破坏。
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();
}
}
isPlatformBrowser是一个函数,用于检查当前应用程序所呈现的平台是否是浏览器。我们给它注入platformId。
它也可以检查变量窗口的存在,为了安全起见,像这样:
if (typeof window != 'undefined')
其他回答
你可以利用observable filter方法更简洁地写这个:
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
this.window.scrollTo(0, 0);
});
如果你在使用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);
});
还有,Angular CDK v6。X现在有一个滚动包,可以帮助处理滚动。
对于iphone/ios safari,您可以使用setTimeout进行包装
setTimeout(function(){
window.scrollTo(0, 1);
}, 0);
从Angular 6.1开始,路由器提供了一个名为scrollPositionRestoration的配置选项,这是为了满足这种情况而设计的。
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled'
}),
...
]
Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.
附注:我只测试了最新版本的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;
}
});
}
}
@Fernando埃切维里亚 太棒了!但是这段代码不能在哈希路由器或惰性路由器中工作。因为它们不会触发位置更改。 可以试试这个:
private lastRouteUrl: string[] = [] ngOnInit(): void { This.router.events.subscribe ((ev) => { const len = this.lastRouteUrl.length if (ev instanceof NavigationEnd) { this.lastRouteUrl.push (ev.url) If (len > 1 && ev。Url === this。lastRouteUrl[len - 2]) { 返回 } 窗口。scrollTo (0, 0) } }) }