Angular 5 在每次单击 Route 时滚动到顶部

IT技术 javascript angular typescript scrolltop angular-router
2021-03-14 16:44:14

我正在使用 angular 5。我有一个仪表板,其中很少有内容很小的部分和很少有内容很大的部分,以至于我在进入顶部时更改路由器时遇到了问题。每次我需要滚动到顶部。谁能帮我解决这个问题,这样当我更换路由器时,我的视图始终保持在顶部。

提前致谢。

6个回答

有一些解决方案,请确保全部检查:)


路由器sockets将activate在实例化新组件时发出事件,因此我们可以使用(activate)滚动(例如)到顶部:

应用程序组件.html

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

app.component.ts

onActivate(event) {
    window.scroll(0,0);
    //or document.body.scrollTop = 0;
    //or document.querySelector('body').scrollTo(0,0)
    ...
}

例如,使用此解决方案来平滑滚动:

    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' }在急切加载的module上使用,它将应用于所有路由:

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

它也将进行平滑滚动,已经。然而,这对于在每个路由上都执行它有不便之处。


另一种解决方案是在路由器动画上进行顶部滚动。在要滚动到顶部的每个过渡中添加此内容:

query(':enter, :leave', style({ position: 'fixed' }), { optional: true }) 
@SahilBabbar,检查 body css,溢出:隐藏?它的高度是多少?
2021-04-21 16:44:14
@Vega 没有。主体的高度是默认的,内部没有硬编码,因为它是一个普通的 Angular 5 应用程序。此外,看看 Angular 文档,他们说scroll事件被 ngzones 列入黑名单。
2021-04-24 16:44:14
试试 document.body.scrollTop = 0; 或使用旧的 js document.querySelector('body').scrollTo(0,0) 等。如果这些不起作用,请提供 MCVE
2021-05-04 16:44:14
window对象上的滚动事件在 angular 5 中不起作用。猜猜为什么?
2021-05-06 16:44:14
有没有办法延迟加载module?
2021-05-20 16:44:14

如果你在 Angular 6 中遇到这个问题,你可以通过将参数添加scrollPositionRestoration: 'enabled'到 app-routing.module.ts 的 RouterModule来解决它

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})
请注意,截至 2019 年 11 月 6 日使用 Angular 8,该scrollPositionRestoration属性至少不适用于动态页面内容(即页面内容异步加载的地方):请参阅此 Angular 错误报告:github.com/angular/angular /问题/24547
2021-05-07 16:44:14

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

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

原答案:

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

<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;
    }
  }
对于 Angular 6+,请使用 Nimesh Nishara Indimagedara 的回答。
2021-04-22 16:44:14
@RobvanMeeuwen,如果我的回答不起作用,那可能是您没有以同样的方式实现它。此解决方案直接操作 DOM 既不正确也不安全
2021-04-25 16:44:14
这个解决方案对我有用(在 Chrome 和 Edge 上测试过)。接受的解决方案不适用于我的项目(Angular5)
2021-05-01 16:44:14
从所有这些解决方案对我来说都是有效的。谢谢@GeoRover
2021-05-08 16:44:14
@Vega,这就是我称之为黑客的原因。您的解决方案是正确的。这里的一些人无法实现你的,所以我提供了后备黑客。他们应该根据他们目前所在的版本重构他们的代码。
2021-05-19 16:44:14

现在,Angular 6.1 提供了一个内置解决方案,并带有scrollPositionRestoration选项。

请参阅Angular 2 的回答Scroll to top on Route Change

从 Angular 版本 6+ 开始不需要使用 window.scroll(0,0)

对于6+来自@ Represents 的Angular 版本用于配置路由器的选项。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) Angular 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]));
}
奇怪的是,每个解决方案在某些情况下都有效,而在其他情况下却失败了。角度滚动到顶部存在严重缺陷。
2021-05-13 16:44:14
我能够将 ViewportScroller 注入到我的组件中。它醒了。
2021-05-17 16:44:14