Route Change에서 Angular 2 맨 위로 스크롤


295

Angular 2 앱에서 페이지를 아래로 스크롤하고 페이지 하단의 링크를 클릭하면 경로가 변경되고 다음 페이지로 이동하지만 페이지 상단으로 스크롤되지는 않습니다. 결과적으로 첫 번째 페이지가 길고 두 번째 페이지에 내용이 적은 경우 두 번째 페이지에 내용이 없다는 인상을줍니다. 내용은 사용자가 페이지 맨 위로 스크롤하는 경우에만 표시되므로

구성 요소의 ngInit에서 페이지 맨 위로 창을 스크롤 할 수 있지만 내 앱의 모든 경로를 자동으로 처리 할 수있는 더 나은 솔루션이 있습니까?


20
Angular 6.1부터 우리는 열심히로드 된 모듈이나 app.module에서 {scrollPositionRestoration : 'enabled'}를 사용할 수 있으며 모든 경로에 적용됩니다. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Manwal

Muito obrigado sua solução funcionou perfeitamente para mim :)
Raphael

한 사람이 초점을 언급하지 않았습니까? 접근성 / 화면 판독기를 올바르게 지원하는 것이 그 어느 때보 다 중요하며 초점을 고려하지 않고 상단으로 스크롤하면 다음 탭 키를 눌러 화면 하단으로 이동할 수 있습니다.
Simon_Weaver

답변:


385

기본 컴포넌트에서 경로 변경 리스너를 등록하고 경로 변경시 맨 위로 스크롤 할 수 있습니다.

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

11
window.scrollTo(0, 0)보다 간결 document.body.scrollTop = 0;하고 읽기 쉬운 IMO입니다.
Mark E. Haase

10
아무도 이것을 구현 한 후에도 아이폰의 사파리 브라우저에서 문제가 지속된다는 것을 눈치 Did을 것입니다. 이견있는 사람?
rgk

1
@mehaase 귀하의 답변이 가장 좋은 것 같습니다. Firefox 데스크톱에서 window.body.scrollTop이 작동하지 않습니다. 감사합니다!
KCarnaille

3
이것은 나를 위해 일했지만 기본 "뒤로"버튼 동작을 손상시킵니다. 되돌아 가면 이전 스크롤 위치를 기억해야합니다.
JackKalish 2016 년

6
이것은 효과가 있었다!! 부드러운 스크롤을 맨 위로 애니메이션 $("body").animate({ scrollTop: 0 }, 1000);하는 대신 추가했지만window.scrollTo(0, 0)
Manubhargav

360

각도 6.1 이상 :

Angular 6.1 (2018-07-25에 릴리스)은 "라우터 스크롤 위치 복원"이라는 기능을 통해이 문제를 처리하기위한 기본 지원 기능을 추가했습니다. 공식 Angular 블로그에 설명 된 것처럼 라우터 구성에서 다음과 같이 활성화하면됩니다.

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

또한 블로그는 "향후 주요 릴리스에서 이것이 기본값이 될 것으로 예상됩니다"라고 말합니다. 지금까지 이것은 Angular 8.2에서 발생하지 않았지만 결국 코드에서 전혀 아무것도 할 필요가 없으며 올바르게 작동합니다.

이 기능에 대한 자세한 내용과 공식 문서 에서이 동작을 사용자 정의하는 방법을 볼 수 있습니다 .

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

2
이것은 앱 구성 요소에서 직접 사용되거나 해당 구성 요소에서 사용되는 단일 구성 요소 (따라서 전체 앱에서 공유)로 이동해야합니다. 예를 들어, 상단 네비게이션 바 구성 요소에 포함 시켰습니다. 모든 구성 요소에 포함해서는 안됩니다.
Fernando Echeverria

3
그렇게하면 코드가 브라우저가 아닌 다른 플랫폼과 더 광범위하게 호환됩니다. 구현 세부 사항 은 stackoverflow.com/q/34177221/2858481 을 참조 하십시오.
Fernando Echeverria 2016 년

3
최신 브라우저에서 뒤로 / 앞으로 단추를 누르고 있으면 바로 이전 / 다음 위치 이외의 위치로 이동할 수있는 메뉴가 나타납니다. 그렇게하면이 솔루션이 깨집니다. 대부분의 경우에 해당하지만 언급 할 가치가 있습니다.
adamdport


1
중첩 된 요소에 대해 "라우터 스크롤 위치 복원"을 활성화하는 방법이 body있습니까?
vulp November

61

각도 6.1에서, 당신은 지금 번거 로움을 피할 수 및 통과 extraOptions당신에게 RouterModule.forRoot()두 번째 매개 변수로하고 지정할 수 있습니다scrollPositionRestoration: enabled 상단 때마다 경로 변화에 스크롤에 각도를 알 수 있습니다.

기본적으로 다음 위치에 있습니다 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 { }

각도 공식 문서


3
위의 답변이 더 설명 적이지만, 나는이 답변이 어디로 가야하는지 정확하게 말해
줬다는

32

관찰 가능한 filter방법 을 활용하여 이것을 간결하게 작성할 수 있습니다 .

this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
      this.window.scrollTo(0, 0);
});

Angular Material 2 사이드 네비게이션을 사용할 때 상단으로 스크롤하는 데 문제가있는 경우 도움이됩니다. 창 또는 문서 본문에는 스크롤 막대가 없으므로 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에는 스크롤 처리에 도움 이되는 스크롤 패키지 가 있습니다.


2
큰! 나를 위해 일한 –document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;
Amir Tugi

mtpultz & @AmirTugi에서 좋은 한 친구. 지금이 문제를 해결하고 당신은 나를 위해 그것을 못 박았다, 건배! md-toolbar가 position : fixed (위)에있을 때 Material 2가 잘 작동하지 않기 때문에 필연적으로 내 측면 탐색을 굴릴 수 있습니다. 너희들 생각이 없다면 .....
팀 하커

내 대답을 찾았을 수도 있습니다 ... stackoverflow.com/a/40396105/3389046
Tim Harker

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

isPlatformBrowser앱이 렌더링되는 현재 플랫폼이 브라우저인지 확인하는 데 사용되는 함수입니다. 우리는 주사를 줘platformId .

또한 다음 windows과 같이 variable의 존재 여부를 확인 하는 것이 안전합니다.

if (typeof window != 'undefined')

1
당신은 주입 할 필요가 없습니다 PLATFORM_IDconstructor와 드에서 매개 변수로이 값을주는 isPlatformBrowser방법을?
Poul Kruijt

1
@PierreDuc 예, 대답이 잘못되었습니다. isPlatformBrowser함수이며 항상 진실합니다. 지금 편집했습니다.
Lazar Ljubenović

감사! 지금 맞습니다! 방금 API를 확인했습니다 : github.com/angular/angular/blob/…
랩터

13

클릭 동작으로 쉽게 할 수 있습니다.

주요 구성 요소 HTML에서 참조 #scrollContainer

<div class="main-container" #scrollContainer>
    <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
</div>

주요 구성 요소 .ts

onActivate(e, scrollContainer) {
    scrollContainer.scrollTop = 0;
}

스크롤되는 요소가 scrollContainer첫 번째 노드에 없을 수 있습니다. 객체에서 약간 파고 들어야 할 수도 있습니다. 나에게 실제로 효과가 있었던 것은scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0
Byron Lopez

13

Angular는 최근 각도 라우팅 모듈 내부에서 아래와 같이 새로운 기능을 도입했습니다.

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

12

가장 좋은 답변은 Angular GitHub 토론에 있습니다 ( 새 페이지에서 경로 변경이 맨 위로 스크롤되지 않음 ).

어쩌면 루트 라우터 변경에서만 맨 위로 가고 싶을 것입니다 (어린이는 아님).

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

JoniJnm에 대한 전체 크레딧 ( 원본 게시물 )



7

각도 6.1로, 라우터가 제공하는 구성 옵션 불리는 scrollPositionRestoration이이 시나리오에 대한 수용하도록 설계된다.

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

4

페이지를 맨 위로 스크롤 해야하는 경우이 작업을 수행 할 수 있습니다 (최상의 해결책은 아니지만 빠름)

document.getElementById('elementId').scrollTop = 0;

4

여기 내가 생각해 낸 해결책이 있습니다. LocationStrategy를 라우터 이벤트와 페어링했습니다. LocationStrategy를 사용하여 사용자가 현재 브라우저 기록을 통과하는시기를 알 수 있도록 부울을 설정합니다. 이렇게하면 URL 및 y 스크롤 데이터를 저장할 필요가 없습니다 (각 데이터가 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;
      }
    });
  }
}

4

이 솔루션은 @FernandoEcheverria 및 @GuilhermeMeireles의 솔루션을 기반으로하지만보다 간결하며 Angular Router가 제공하는 popstate 메커니즘과 함께 작동합니다. 이를 통해 여러 개의 연속 탐색의 스크롤 레벨을 저장하고 복원 할 수 있습니다.

각 탐색 상태에 대한 스크롤 위치를지도에 저장 scrollLevels합니다. popstate 이벤트가 발생하면, 복원 될 상태의 ID는 Angular Router에 의해 제공됩니다 : event.restoredState.navigationId. 그런 다음에서 해당 상태의 마지막 스크롤 레벨을 가져 오는 데 사용됩니다 scrollLevels.

경로에 저장된 스크롤 수준이 없으면 예상대로 맨 위로 스크롤됩니다.

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class AppComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
    const scrollLevels: { [navigationId: number]: number } = {};
    let lastId = 0;
    let restoredId: number;

    this.router.events.subscribe((event: Event) => {

      if (event instanceof NavigationStart) {
        scrollLevels[lastId] = window.scrollY;
        lastId = event.id;
        restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
      }

      if (event instanceof NavigationEnd) {
        if (restoredId) {
          // Optional: Wrap a timeout around the next line to wait for
          // the component to finish loading
          window.scrollTo(0, scrollLevels[restoredId] || 0);
        } else {
          window.scrollTo(0, 0);
        }
      }

    });
  }

}

대박. 창 대신 div를 스크롤하기 위해 약간의 사용자 정의 버전을 만들어야했지만 효과가있었습니다. 한 가지 중요한 차이점은 scrollTopvs scrollY입니다.
BBaysinger

4

아래 그림과 같이 @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)
            });
        }
    }

그런 다음 스 니펫을 아래에 추가하십시오.

 html {
      scroll-behavior: smooth;
    }

당신의 styles.css에


1

아이폰 / iOS 사파리의 경우 setTimeout으로 래핑 할 수 있습니다

setTimeout(function(){
    window.scrollTo(0, 1);
}, 0);

필자의 경우 페이지 줄 바꿈 요소 css도 설정해야했습니다. height: 100vh + 1px;
tubbsy 2016 년

1

안녕하세요, 각도 4에서 저에게 효과적입니다. 라우터 변경을 스크롤하기 위해 부모를 참조하면됩니다.

layout.component.pug

.wrapper(#outlet="")
    router-outlet((activate)='routerActivate($event,outlet)')

layout.component.ts

 public routerActivate(event,outlet){
    outlet.scrollTop = 0;
 }`

1
퍼그를 배우는 것을 귀찮게하지는 않지만 내 게으름을 용서하지만 HTML로 번역 할 수 있습니까?
CodyBugstein

0

@Fernando Echeverria 위대한! 그러나이 코드는 해시 라우터 또는 지연 라우터에서 작동하지 않습니다. 위치 변경을 트리거하지 않기 때문입니다. 이것을 시도 할 수 있습니다 :

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]) {
        return
      }
      window.scrollTo(0, 0)
    }
  })
}


0

Router자체를 사용하면 일관된 브라우저 환경을 유지하기 위해 완전히 극복 할 수없는 문제가 발생합니다. 내 생각에 가장 좋은 방법은 사용자 정의를 사용하고 directive클릭시 스크롤을 재설정하는 것입니다. 이것에 대한 좋은 점은 url클릭 하는 것과 동일 하면 페이지가 맨 위로 스크롤된다는 것입니다. 이는 일반적인 웹 사이트와 일치합니다. 기본 directive은 다음과 같습니다.

import {Directive, HostListener} from '@angular/core';

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @HostListener('click')
    onClick(): void {
        window.scrollTo(0, 0);
    }
}

다음 사용법으로 :

<a routerLink="/" linkToTop></a>

대부분의 유스 케이스에는 충분하지만 다음과 같은 문제가 발생할 수 있습니다.

  • universal사용 으로 인해 작동하지 않습니다window
  • 클릭 할 때마다 트리거되므로 변경 감지에 작은 속도 영향
  • 이 지시문을 비활성화 할 방법이 없습니다

실제로 이러한 문제를 극복하는 것은 매우 쉽습니다.

@Directive({
  selector: '[linkToTop]'
})
export class LinkToTopDirective implements OnInit, OnDestroy {

  @Input()
  set linkToTop(active: string | boolean) {
    this.active = typeof active === 'string' ? active.length === 0 : active;
  }

  private active: boolean = true;

  private onClick: EventListener = (event: MouseEvent) => {
    if (this.active) {
      window.scrollTo(0, 0);
    }
  };

  constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
              private readonly elementRef: ElementRef,
              private readonly ngZone: NgZone
  ) {}

  ngOnDestroy(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
    }
  }

  ngOnInit(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.ngZone.runOutsideAngular(() => 
        this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
      );
    }
  }
}

이를 위해서는 기본 사용 사례와 동일한 사용법으로 대부분의 사용 사례를 고려하고 활성화 / 비활성화합니다.

<a routerLink="/" linkToTop></a> <!-- always active -->
<a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->

광고하고 싶지 않다면 광고를 읽지 마십시오.

브라우저가 passive이벤트를 지원하는지 여부를 확인하기 위해 또 다른 개선이 이루어질 수 있습니다 . 이것은 코드를 조금 더 복잡하게 만들고 사용자 지정 지시문 / 템플릿에서 이러한 코드를 모두 구현하려는 경우 다소 모호합니다. 그렇기 때문에 이러한 문제를 해결하는 데 사용할 수 있는 작은 라이브러리 를 작성했습니다 . 위와 동일한 기능을 추가하고 passive이벤트를 추가 하려면 ng-event-options라이브러리 를 사용하는 경우 지시문을 이것으로 변경할 수 있습니다 . 논리는 click.pnb리스너 내부에 있습니다 .

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @Input()
    set linkToTop(active: string|boolean) {
        this.active = typeof active === 'string' ? active.length === 0 : active;
    }

    private active: boolean = true;

    @HostListener('click.pnb')
    onClick(): void {
      if (this.active) {
        window.scrollTo(0, 0);
      }        
    }
}

0

이것은 해시 탐색을 포함한 모든 탐색 변경에 가장 효과적이었습니다.

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this._sub = this.route.fragment.subscribe((hash: string) => {
    if (hash) {
      const cmp = document.getElementById(hash);
      if (cmp) {
        cmp.scrollIntoView();
      }
    } else {
      window.scrollTo(0, 0);
    }
  });
}

0

이 코드의 주요 아이디어는 방문한 모든 URL과 각각의 scrollY 데이터를 배열로 유지하는 것입니다. 사용자가 페이지를 포기할 때마다 (NavigationStart)이 배열이 업데이트됩니다. 사용자가 새 페이지 (NavigationEnd)를 입력 할 때마다 Y 위치를 복원할지 또는이 페이지에 어떻게 도달하는지에 따라 결정하지 않습니다. 일부 페이지에서 참조가 사용 된 경우 0으로 스크롤합니다. 브라우저 뒤로 / 앞으로 기능을 사용하는 경우 배열에 저장된 Y로 스크롤합니다. 내 영어 죄송합니다 :)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Location, PopStateEvent } from '@angular/common';
import { Router, Route, RouterLink, NavigationStart, NavigationEnd, 
    RouterEvent } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'my-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {

  private _subscription: Subscription;
  private _scrollHistory: { url: string, y: number }[] = [];
  private _useHistory = false;

  constructor(
    private _router: Router,
    private _location: Location) {
  }

  public ngOnInit() {

    this._subscription = this._router.events.subscribe((event: any) => 
    {
      if (event instanceof NavigationStart) {
        const currentUrl = (this._location.path() !== '') 
           this._location.path() : '/';
        const item = this._scrollHistory.find(x => x.url === currentUrl);
        if (item) {
          item.y = window.scrollY;
        } else {
          this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
        }
        return;
      }
      if (event instanceof NavigationEnd) {
        if (this._useHistory) {
          this._useHistory = false;
          window.scrollTo(0, this._scrollHistory.find(x => x.url === 
          event.url).y);
        } else {
          window.scrollTo(0, 0);
        }
      }
    });

    this._subscription.add(this._location.subscribe((event: PopStateEvent) 
      => { this._useHistory = true;
    }));
  }

  public ngOnDestroy(): void {
    this._subscription.unsubscribe();
  }
}

0

window.scrollTo()Angular 5에서는 작동하지 않으므로 다음 document.body.scrollTop과 같이 사용했습니다 .

this.router.events.subscribe((evt) => {
   if (evt instanceof NavigationEnd) {
      document.body.scrollTop = 0;
   }
});

0

동일한 경로로 다른 구성 요소를로드하는 경우 ViewportScroller를 사용하여 동일한 것을 수행 할 수 있습니다.

import { ViewportScroller } from '@angular/common';

constructor(private viewportScroller: ViewportScroller) {}

this.viewportScroller.scrollToPosition([0, 0]);

0

window scroll top
window.pageYOffset과 document.documentElement.scrollTop은 모든 경우에 동일한 결과를 반환합니다. IE 9에서는 window.pageYOffset이 지원되지 않습니다.

app.component.ts

import { Component, HostListener, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  isShow: boolean;
  topPosToStartShowing = 100;

  @HostListener('window:scroll')
  checkScroll() {

    const scrollPosition = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

    console.log('[scroll]', scrollPosition);

    if (scrollPosition >= this.topPosToStartShowing) {
      this.isShow = true;
    } else {
      this.isShow = false;
    }
  }

  gotoTop() {
    window.scroll({ 
      top: 0, 
      left: 10, 
      behavior: 'smooth' 
    });
  }
}

app.component.html

<style>
  p {
  font-family: Lato;
}

button {
  position: fixed;
  bottom: 5px;
  right: 5px;
  font-size: 20px;
  text-align: center;
  border-radius: 5px;
  outline: none;
}
  </style>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>

<button *ngIf="isShow" (click)="gotoTop()">👆</button>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.