防止在 Angular 中的单个 router.navigate 调用上滚动到顶部

问题描述 投票:0回答:4

我的 Angular 8 应用程序在导航到新页面时滚动到顶部。在一个特定页面上我有一个可排序的表格。导航到该页面时,它应该滚动到顶部,但是当单击表头单元格时,它应该使用排序更新查询参数,但滚动到顶部。

是否可以使用新的查询参数数据调用

router.navigate(...)
而不触发滚动到顶部,同时不禁用从路线本身滚动到顶部?

angular routes
4个回答
5
投票

您可以使用多个选项配置路由器模块。您应该能够使用 scrollPositionRestoration 选项保留滚动。

您可以像这样使用它:

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

话虽如此,此选项将保留所有页面的滚动位置。

如果您只想针对特定页面实现此目的,则可以选择在 navigate 调用中使用

navigationExtras
并在 state 对象中指定当前滚动位置,并在
AfterViewInit
处理程序更新滚动位置时。

假设您有一个包含表的容器,您可以使用

ViewChild
装饰器在组件文件中访问它。

// declare your container component
@ViewChild("container")
private container: ElementRef;

// after view init updated current scroll position
ngAfterViewInit() {
  const prevScrollPos = this.router.getCurrentNavigation()?.extras?.state?.scrollTop;
  if (prevScrollPos) {
    this.container.nativeElement.scrollTop = prevScrollPos;
  }
}

// specify scroll position on navigation
this.router.navigate(
  ['/login'],
  {
    state: { scrollTop: this.container.nativeElement.scrollTop }
  }
);

2
投票

由于导航()方法返回一个承诺,一旦承诺解决,您就可以滚动到特定位置:

let currentScrollHeight = window.pageYOffset
this.router.navigate(['my-page']).then(() => window.scrollTo({ top: currentScrollHeight }))

或者,如果你像我一样使用 rxjs,你可以将 Promise 转换为 observable 并执行相同的操作:

let currentScrollHeight = window.pageYOffset
from(this.router.navigate(['my-page'])).pipe(
  first(),
  tap(() => window.scrollTo({ top: currentScrollHeight }))
).subscribe()

此方法不会在我的机器上产生任何闪烁/跳跃,这正是我所希望的。


0
投票

单击锚点时,将

@Viewchild
block:'nearest'
结合使用,以防止页面跳转到顶部:

@ViewChild("el") private el: ElementRef;

this.el.nativeElement.scrollIntoView({ behavior: "smooth", block:'nearest' });

0
投票

我最近遇到了同样的问题,并想出了一个新颖的解决方案。 它仍然很老套,但至少它是相当封闭的,不需要特殊的配置或逻辑分布在应用程序的多个部分。

Angular 的路由器使用 window.scrollTo 方法滚动回顶部,为什么不暂时禁用该方法并在导航后重新启用它:

export class MyComponent {
    static readonly windowScrollToBackup = window.scrollTo;
    
    navigateWithoutScrollToTop(url: UrlTree) {
       window.scrollTo = () => {};
       this.router.navigateByUrl(url).then(() => {
           setTimeout(() => {
               window.scrollTo = MyComponent.windowScrollToBackup;
           }, 0);
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.