Angular 5在每次路线点击时滚动到顶部

问题描述 投票:47回答:12

我正在使用角度5.我有一个仪表板,我有几个部分内容很少,几个部分内容如此之大,以至于我在更换路由器时遇到问题。每次我需要滚动到顶部。任何人都可以帮助我解决这个问题,以便当我更改路由器时,我的视图始终保持在顶部。

提前致谢。

angular typescript scrolltop angular-router
12个回答
117
投票

每当实例化新组件时,路由器插座都会发出激活事件,因此(activate)事件可以滚动(例如)到顶部:

app.component.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)
    ...
}

或者使用this answer来平滑滚动

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

如果你希望有选择性,说不是每个组件都应该触发滚动,你可以检查它:

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


Since Angular6.1, we can also use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes:
RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

它还可以进行平滑滚动


1
投票

试试这个:

app.component.ts

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

1
投票

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

}

1
投票

组件:订阅所有路由事件,而不是在模板中创建一个动作,并在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);
  }

}

HTML

<router-outlet></router-outlet>

25
投票

如果您在Angular 6中遇到此问题,可以通过将参数scrollPositionRestoration: 'enabled'添加到app-routing.module.ts的RouterModule来修复它:

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

enter image description here


14
投票

现在有一个内置的解决方案,可以在Angular 6.1中使用scrollPositionRestoration选项。

请参阅my answer上的Angular 2 Scroll to top on Route Change


13
投票

编辑:对于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;
    }
  }

4
投票

尽管@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;
      }
    });
  }
}

2
投票

在我的情况下,我刚刚补充说

window.scroll(0,0);

ngOnInit()及其工作正常。


1
投票

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

在每个组件中:

export class MyComponent implements OnInit {

firstLoad: boolean = true;

...

ngOnInit() {

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

1
投票

我一直在寻找像AngularJS中那样的问题的内置解决方案。但在此之前,此解决方案适用于我,它很简单,并保留了后退按钮功能。

app.component.html

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

app.component.ts

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

zurfyx original post的回答


1
投票

您只需要创建一个包含屏幕滚动调整的功能

例如

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

window.scrollTo(xpos,ypos) - >预期参数。

© www.soinside.com 2019 - 2024. All rights reserved.