Używam kątowej 5. Mam pulpit nawigacyjny, w którym mam kilka sekcji z małą zawartością i kilka sekcji z tak dużą zawartością, że mam problem ze zmianą routera podczas przechodzenia na górę. Za każdym razem, gdy muszę przewijać, aby przejść do góry. Czy ktoś może mi pomóc rozwiązać ten problem, aby po zmianie routera mój widok był zawsze na górze.
Z góry dziękuję.
Odpowiedzi:
Jest kilka rozwiązań, koniecznie sprawdź je wszystkie :)
Gniazdo routera wyemituje
activate
zdarzenie za każdym razem, gdy tworzony jest nowy komponent, więc możemy użyć(activate)
do przewijania (na przykład) do góry: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) ... }
Użyj na przykład tego rozwiązania do płynnego przewijania:
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); }
Jeśli chcesz być selektywny, powiedz, że nie każdy komponent powinien wywoływać przewijanie, możesz to sprawdzić w
if
instrukcji takiej jak ta:onActivate(e) { if (e.constructor.name)==="login"{ // for example window.scroll(0,0); } }
Od Angular6.1 możemy również używać
{ scrollPositionRestoration: 'enabled' }
na chętnie ładowanych modułach i będzie to zastosowane do wszystkich tras:RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Będzie również wykonywać płynne przewijanie. Jednak jest to niewygodne przy każdym routingu.
Innym rozwiązaniem jest przewijanie w górę animacji routera. Dodaj to w każdym przejściu, w którym chcesz przewinąć do góry:
query(':enter, :leave', style({ position: 'fixed' }), { optional: true })
źródło
window
obiektu nie działają w trybie kątowym 5. Jakieś przypuszczenia dlaczego?Jeśli napotkasz ten problem w Angular 6, możesz go naprawić, dodając parametr
scrollPositionRestoration: 'enabled'
do RouterModule app-routing.module.ts:@NgModule({ imports: [RouterModule.forRoot(routes,{ scrollPositionRestoration: 'enabled' })], exports: [RouterModule] })
źródło
scrollPositionRestoration
właściwość nie działa z dynamiczną zawartością strony (tj. GdyEDYCJA: W przypadku Angular 6+ użyj odpowiedzi Nimesh Nishara Indimagedara, wspominając:
RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' });
Oryginalna odpowiedź:
Jeśli wszystko zawiedzie, utwórz pusty element HTML (np .: div) na górze (lub przewiń do lokalizacji) z id = "top" w szablonie (lub szablonie nadrzędnym):
<div id="top"></div>
I w komponencie:
ngAfterViewInit() { // Hack: Scrolls to top of Page after page view initialized let top = document.getElementById('top'); if (top !== null) { top.scrollIntoView(); top = null; } }
źródło
Teraz w Angular 6.1 dostępne jest wbudowane rozwiązanie z
scrollPositionRestoration
opcją.Zobacz moją odpowiedź w Angular 2 Przewiń do góry w sekcji Zmiana trasy .
źródło
Chociaż @Vega zapewnia bezpośrednią odpowiedź na twoje pytanie, są pewne problemy. Łamie przycisk wstecz / dalej przeglądarki. Jeśli użytkownik kliknie przycisk wstecz lub do przodu w przeglądarce, straci on swoje miejsce i zostanie przewinięty na górze. Może to być trochę uciążliwe dla użytkowników, jeśli musieli przewinąć w dół, aby dostać się do łącza i zdecydowali się kliknąć wstecz, tylko po to, aby stwierdzić, że pasek przewijania został zresetowany do góry.
Oto moje rozwiązanie problemu.
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; } }); } }
źródło
W moim przypadku właśnie dodałem
window.scroll(0,0);
w
ngOnInit()
i jego pracy grzywny.źródło
Od wersji Angular 6+ Nie ma potrzeby używania window.scroll (0,0)
Dla wersji Angular
6+
od @ Przedstawia opcje konfiguracji routera.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' }
Można użyć
scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
wPrzykład:
RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled'|'top' });
A jeśli ktoś wymaga ręcznego sterowania przewijaniem, nie ma potrzeby używania
window.scroll(0,0)
Zamiast tego wprowadzono wspólny pakiet Angular V6ViewPortScoller
.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 }
Użycie jest dość proste Przykład:
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])); }
źródło
jeśli używasz mat-sidenav, podaj identyfikator do gniazda routera (jeśli masz nadrzędne i podrzędne gniazda routera) i użyj w nim funkcji aktywuj
<router-outlet id="main-content" (activate)="onActivate($event)">
i użyj tego selektora zapytania „mat-sidenav-content”, aby przewinąć góręonActivate(event) { document.querySelector("mat-sidenav-content").scrollTo(0, 0); }
źródło
id
(mam jedenrouter-outlet
w mojej aplikacji). Zrobiłem to również w sposób bardziej „kanciasty”:@ViewChild(MatSidenavContainer) sidenavContainer: MatSidenavContainer; onActivate() { this.sidenavContainer.scrollable.scrollTo({ left: 0, top: 0 }); }
Ciągle szukam wbudowanego rozwiązania tego problemu, takiego jak w AngularJS. Ale do tego czasu to rozwiązanie działa dla mnie, jest proste i zachowuje funkcjonalność przycisku Wstecz.
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) }
Odpowiedź użytkownika zurfyx original post
źródło
Wystarczy stworzyć funkcję, która zawiera regulację przewijania ekranu
na przykład
window.scroll(0,0) OR window.scrollTo() by passing appropriate parameter.
window.scrollTo (xpos, ypos) -> oczekiwany parametr.
źródło
Angular 6.1 i nowsze:
Możesz skorzystać z wbudowanego rozwiązania dostępnego w Angular 6.1+ z opcją,
scrollPositionRestoration: 'enabled'
aby osiągnąć to samo.@NgModule({ imports: [RouterModule.forRoot(routes,{ scrollPositionRestoration: 'enabled' })], exports: [RouterModule] })
Angular 6.0 i starsze:
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); } }); } }
Uwaga: oczekiwanym zachowaniem jest to, że po powrocie do strony powinna pozostać przewinięta w dół do tej samej lokalizacji, w której znajdowała się po kliknięciu łącza, ale przewijana do góry po przejściu na każdą stronę.
źródło
Oto rozwiązanie, które przewija się do góry komponentu tylko przy pierwszej wizycie dla KAŻDEGO komponentu (na wypadek, gdybyś musiał zrobić coś innego dla każdego komponentu):
W każdym komponencie:
export class MyComponent implements OnInit { firstLoad: boolean = true; ... ngOnInit() { if(this.firstLoad) { window.scroll(0,0); this.firstLoad = false; } ... }
źródło
export class AppComponent { constructor(private router: Router) { router.events.subscribe((val) => { if (val instanceof NavigationEnd) { window.scrollTo(0, 0); } }); } }
źródło
poprostu dodaj
window.scrollTo({ top: 0);
to ngOnInit ()
źródło
Dla kogoś, kto szuka funkcji przewijania, po prostu dodaj tę funkcję i wywołaj, gdy zajdzie taka potrzeba
scrollbarTop(){ window.scroll(0,0); }
źródło
Spróbuj tego:
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(); } }
źródło
Komponent: zasubskrybuj wszystkie zdarzenia routingu zamiast tworzyć akcję w szablonie i przewijaj na NavigationEnd b / c, w przeciwnym razie uruchomisz to w przypadku złej nawigacji lub zablokowanych tras itp ... Jest to pewny sposób, aby wiedzieć, że jeśli trasa została pomyślnie pokonana, a następnie przewiń. W przeciwnym razie nic nie rób.
@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
źródło
Spróbuj tego
@NgModule({ imports: [RouterModule.forRoot(routes,{ scrollPositionRestoration: 'top' })], exports: [RouterModule] })
ten kod obsługuje kątowe 6 <=
źródło