Wenn ich in meiner Angular 2-App eine Seite nach unten scrolle und auf den Link unten auf der Seite klicke, ändert sich die Route und ich komme zur nächsten Seite, aber nicht zum oberen Rand der Seite. Wenn die erste Seite lang ist und die zweite Seite nur wenige Inhalte enthält, entsteht der Eindruck, dass der zweiten Seite der Inhalt fehlt. Da der Inhalt nur sichtbar ist, wenn der Benutzer zum Anfang der Seite blättert.
Ich kann das Fenster in ngInit der Komponente zum Anfang der Seite scrollen. Gibt es jedoch eine bessere Lösung, die alle Routen in meiner App automatisch verarbeitet?
RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Antworten:
Sie können einen Listener für Routenänderungen in Ihrer Hauptkomponente registrieren und bei Routenänderungen nach oben scrollen.
quelle
window.scrollTo(0, 0)
ist eine prägnanteredocument.body.scrollTop = 0;
und besser lesbare IMO.$("body").animate({ scrollTop: 0 }, 1000);
anstattwindow.scrollTo(0, 0)
das reibungslose Scrollen nach oben zu animierenWinkel 6.1 und höher :
Angular 6.1 (veröffentlicht am 25.07.2018) hat eine integrierte Unterstützung hinzugefügt, um dieses Problem durch eine Funktion namens "Wiederherstellung der Router-Bildlaufposition" zu beheben. Wie im offiziellen Angular-Blog beschrieben , müssen Sie dies nur in der Routerkonfiguration wie folgt aktivieren:
Darüber hinaus heißt es im Blog: "Es wird erwartet, dass dies in einer zukünftigen Hauptversion zum Standard wird." Bisher ist dies nicht geschehen (ab Angular 8.2), aber irgendwann müssen Sie in Ihrem Code überhaupt nichts mehr tun, und dies funktioniert sofort einwandfrei.
Weitere Details zu dieser Funktion und zum Anpassen dieses Verhaltens finden Sie in den offiziellen Dokumenten .
Winkel 6.0 und früher :
Während die hervorragende Antwort von @ GuilhermeMeireles das ursprüngliche Problem behebt, wird ein neues eingeführt, indem das normale Verhalten, das Sie beim Zurück- oder Vorwärtsnavigieren erwarten (mit Browsertasten oder über Position im Code), gebrochen wird. Das erwartete Verhalten ist, dass beim Zurücknavigieren zur Seite der Bildlauf an derselben Stelle fortgesetzt werden sollte, an der Sie auf den Link geklickt haben. Wenn Sie jedoch auf jeder Seite nach oben scrollen, wird diese Erwartung offensichtlich gebrochen.
Der folgende Code erweitert die Logik, um diese Art der Navigation zu erkennen, indem die PopStateEvent-Sequenz von Location abonniert und die Logik zum Scrollen nach oben übersprungen wird, wenn die neu erreichte Seite ein Ergebnis eines solchen Ereignisses ist.
Wenn die Seite, von der aus Sie zurück navigieren, lang genug ist, um das gesamte Ansichtsfenster abzudecken, wird die Bildlaufposition automatisch wiederhergestellt. Wenn @JordanNelson jedoch richtig darauf hingewiesen hat, müssen Sie bei einer kürzeren Seite die ursprüngliche Bildlaufposition verfolgen und wiederherstellen explizit, wenn Sie zur Seite zurückkehren. Die aktualisierte Version des Codes deckt auch diesen Fall ab, indem die Bildlaufposition immer explizit wiederhergestellt wird.
quelle
body
?Ab Angular 6.1 können Sie jetzt den Ärger vermeiden und als zweiten Parameter
extraOptions
an Ihren übergeben. SieRouterModule.forRoot()
können festlegenscrollPositionRestoration: enabled
, dass Angular angewiesen wird, bei jeder Änderung der Route nach oben zu scrollen.Standardmäßig finden Sie dies in
app-routing.module.ts
:Angular Official Docs
quelle
Sie können dies prägnanter schreiben, indem Sie die beobachtbare
filter
Methode nutzen:Wenn Sie Probleme haben, bei Verwendung des Seitenavs Angular Material 2 nach oben zu scrollen, ist dies hilfreich. Das Fenster oder der Dokumentkörper verfügt nicht über die Bildlaufleiste. Sie müssen daher den
sidenav
Inhaltscontainer abrufen und dieses Element scrollen. Andernfalls versuchen Sie standardmäßig, das Fenster zu scrollen.Außerdem verfügt das Angular CDK v6.x jetzt über ein Bildlaufpaket , das bei der Handhabung des Bildlaufs hilfreich sein kann.
quelle
document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;
Wenn Sie serverseitiges Rendern haben, sollten Sie darauf achten, den Code nicht
windows
auf dem Server auszuführen, auf dem diese Variable nicht vorhanden ist. Dies würde zu einem Codebruch führen.isPlatformBrowser
ist eine Funktion, mit der überprüft wird, ob die aktuelle Plattform, auf der die App gerendert wird, ein Browser ist oder nicht. Wir geben ihm die SpritzeplatformId
.Es ist auch möglich, die Existenz einer Variablen zu überprüfen
windows
, um sicher zu sein, wie folgt:quelle
PLATFORM_ID
in die Methode injizierenconstructor
und diesen Wert als ParameterisPlatformBrowser
angeben?isPlatformBrowser
ist eine Funktion und wird immer wahr sein. Ich habe es jetzt bearbeitet.Machen Sie es sich einfach mit einer Klickaktion
Machen Sie in Ihrer Hauptkomponente HTML den Verweis #scrollContainer
in der Hauptkomponente .ts
quelle
scrollContainer
ersten Knoten. Möglicherweise müssen Sie ein wenig in das Objekt graben. Für mich war es das, was wirklich funktioniert hatscrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0
Angular hat kürzlich eine neue Funktion eingeführt. Innerhalb des Angular-Routing-Moduls werden Änderungen wie unten vorgenommen
quelle
Die beste Antwort finden Sie in der Angular GitHub-Diskussion ( Ändern der Route wird auf der neuen Seite nicht nach oben gescrollt ).
app.component.html
app.component.ts
Volle Credits an JoniJnm ( Originalbeitrag )
quelle
Sie können Ihrer Komponente den AfterViewInit- Lebenszyklus-Hook hinzufügen .
quelle
Ab Angular 6.1 bietet der Router eine Konfigurationsoption namens
scrollPositionRestoration
, die für dieses Szenario ausgelegt ist.quelle
Wenn Sie einfach die Seite nach oben scrollen müssen, können Sie dies tun (nicht die beste Lösung, aber schnell).
quelle
Hier ist eine Lösung, die ich mir ausgedacht habe. Ich habe die LocationStrategy mit den Router-Ereignissen gepaart. Verwenden der LocationStrategy zum Festlegen eines Booleschen Werts, um festzustellen, wann ein Benutzer gerade den Browserverlauf durchläuft. Auf diese Weise muss ich keine URL- und Y-Scroll-Daten speichern (was ohnehin nicht gut funktioniert, da alle Daten basierend auf der URL ersetzt werden). Dies löst auch den Randfall, wenn ein Benutzer die Zurück- oder Vorwärts-Taste in einem Browser gedrückt hält und mehrere Seiten anstatt nur einer Seite vorwärts oder rückwärts geht.
PS Ich habe nur die neueste Version von IE, Chrome, FireFox, Safari und Opera getestet (Stand dieses Beitrags).
Hoffe das hilft.
quelle
Diese Lösung basiert auf der Lösung von @ FernandoEcheverria und @ GuilhermeMeireles, ist jedoch präziser und funktioniert mit den Popstate-Mechanismen, die der Angular Router bietet. Dies ermöglicht das Speichern und Wiederherstellen der Bildlaufebene mehrerer aufeinanderfolgender Navigationen.
Wir speichern die Bildlaufpositionen für jeden Navigationsstatus in einer Karte
scrollLevels
. Sobald ein Popstate-Ereignis vorliegt, wird die ID des Status, der wiederhergestellt werden soll, vom Angular Router bereitgestellt :event.restoredState.navigationId
. Dies wird dann verwendet, um die letzte Bildlaufebene dieses Status abzurufenscrollLevels
.Wenn für die Route keine gespeicherte Bildlaufebene vorhanden ist, wird wie erwartet nach oben gescrollt.
quelle
scrollTop
vsscrollY
.Zusätzlich zu der perfekten Antwort von @Guilherme Meireles (siehe unten) können Sie Ihre Implementierung optimieren, indem Sie einen reibungslosen Bildlauf wie unten gezeigt hinzufügen
Fügen Sie dann das folgende Snippet hinzu
zu Ihren styles.css
quelle
für iphone / ios safari kannst du mit einem setTimeout einpacken
quelle
height: 100vh + 1px;
Hallo Leute, das funktioniert bei mir in Winkel 4. Sie müssen nur auf das übergeordnete Element verweisen, um beim Routerwechsel einen Bildlauf durchzuführen
layout.component.pug
layout.component.ts
quelle
@ Fernando Echeverria großartig! Dieser Code funktioniert jedoch nicht im Hash-Router oder im Lazy-Router. weil sie keine Standortänderungen auslösen. kann das versuchen:
quelle
Die Verwendung von
Router
selbst führt zu Problemen, die Sie nicht vollständig überwinden können, um eine konsistente Browser-Erfahrung zu gewährleisten. Meiner Meinung nach ist die beste Methode, einfach eine benutzerdefinierte zu verwendendirective
und die Schriftrolle beim Klicken zurücksetzen zu lassen. Das Gute daran ist, dassurl
die Seite auch nach oben zurückblättert , wenn Sie sich auf der gleichen Seite befinden, auf die Sie geklickt haben. Dies steht im Einklang mit normalen Websites. Das Basicdirective
könnte ungefähr so aussehen:Mit folgender Verwendung:
Dies wird für die meisten Anwendungsfälle ausreichen, aber ich kann mir einige Probleme vorstellen, die sich daraus ergeben können:
universal
wegen der Verwendung vonwindow
Es ist eigentlich ganz einfach, diese Probleme zu lösen:
Dies berücksichtigt die meisten Anwendungsfälle mit der gleichen Verwendung wie die Basis mit dem Vorteil, dass sie aktiviert / deaktiviert werden:
Werbespots, lesen Sie nicht, wenn Sie nicht beworben werden möchten
Eine weitere Verbesserung könnte vorgenommen werden, um zu überprüfen, ob der Browser
passive
Ereignisse unterstützt oder nicht . Dies macht den Code etwas komplizierter und ist etwas unklar, wenn Sie all dies in Ihre benutzerdefinierten Anweisungen / Vorlagen implementieren möchten. Deshalb habe ich eine kleine Bibliothek geschrieben, mit der Sie diese Probleme angehen können. Um die gleiche Funktionalität wie oben und mit dem hinzugefügtenpassive
Ereignis zu haben, können Sie Ihre Direktive in diese ändern, wenn Sie dieng-event-options
Bibliothek verwenden. Die Logik ist imclick.pnb
Hörer:quelle
Dies funktionierte für mich am besten für alle Navigationsänderungen einschließlich der Hash-Navigation
quelle
Die Hauptidee hinter diesem Code besteht darin, alle besuchten URLs zusammen mit den entsprechenden scrollY-Daten in einem Array zu speichern. Jedes Mal, wenn ein Benutzer eine Seite verlässt (NavigationStart), wird dieses Array aktualisiert. Jedes Mal, wenn ein Benutzer eine neue Seite betritt (NavigationEnd), entscheiden wir uns, die Y-Position wiederherzustellen oder nicht, je nachdem, wie wir zu dieser Seite gelangen. Wenn ein Verweis auf einer Seite verwendet wurde, scrollen wir zu 0. Wenn Browser-Vorwärts- / Rückwärtsfunktionen verwendet wurden, scrollen wir zu Y, das in unserem Array gespeichert ist. Entschuldigung für mein Englisch :)
quelle
window.scrollTo()
funktioniert nicht für mich in Angular 5, also habe ichdocument.body.scrollTop
wie verwendet,quelle
Wenn Sie verschiedene Komponenten mit derselben Route laden, können Sie mit ViewportScroller dasselbe erreichen.
quelle
Fenster nach oben scrollen
Sowohl window.pageYOffset als auch document.documentElement.scrollTop geben in allen Fällen das gleiche Ergebnis zurück. window.pageYOffset wird unter IE 9 nicht unterstützt.
app.component.ts
app.component.html
quelle