Navigation API
Experimentell: Dies ist eine experimentelle Technologie
Überprüfen Sie die Browser-Kompatibilitätstabelle sorgfältig, bevor Sie diese produktiv verwenden.
Die Navigation API bietet die Möglichkeit, Navigationsaktionen des Browsers zu initiieren, abzufangen und zu verwalten. Außerdem kann sie die Einträge in der Historie einer Anwendung untersuchen. Dies ist ein Nachfolger früherer Webplattform-Funktionen wie der History API und window.location
, die deren Schwächen behebt und speziell auf die Bedürfnisse von Single-Page-Applications (SPAs) ausgerichtet ist.
Konzepte und Nutzung
In SPAs bleibt die Seitenvorlage während der Nutzung in der Regel gleich, und der Inhalt wird dynamisch umgeschrieben, wenn der Benutzer verschiedene Seiten oder Funktionen aufruft. Dadurch wird nur eine eindeutige Seite im Browser geladen, was das erwartete Benutzererlebnis des Navigierens zwischen verschiedenen Orten in der Verlaufshistorie stört. Dieses Problem kann teilweise über die History API gelöst werden, aber sie ist nicht auf die Bedürfnisse von SPAs ausgelegt. Die Navigation API soll diese Lücke schließen.
Die API wird über die Window.navigation
Eigenschaft aufgerufen, die eine Referenz auf ein globales Navigation
Objekt zurückgibt. Jedes window
Objekt hat seine eigene entsprechende navigation
Instanz.
Umgang mit Navigationen
Das navigation
Interface hat mehrere zugehörige Ereignisse, das bemerkenswerteste ist das navigate
Ereignis. Dieses wird ausgelöst, wenn eine Art von Navigation eingeleitet wird, was bedeutet, dass Sie alle Seitennavigationen von einem zentralen Punkt aus steuern können; ideal für die Routing-Funktionalität in SPA-Frameworks. (Dies ist nicht der Fall bei der History API, bei der es manchmal schwierig ist, zu reagieren, um alle Navigationen zu erfassen.) Der navigate
Ereignishandler erhält ein NavigateEvent
Objekt, das detaillierte Informationen enthält, einschließlich Einzelheiten über das Navigationsziel, den Typ, ob es POST
Formulardaten oder eine Download-Anfrage enthält, und mehr.
Das NavigationEvent
Objekt bietet auch zwei Methoden:
intercept()
nimmt als Argument eine Rückruffunktion, die ein Versprechen zurückgibt. Es ermöglicht Ihnen zu kontrollieren, was passiert, wenn die Navigation eingeleitet wird. Zum Beispiel kann es im Fall eines SPAs verwendet werden, um relevanten neuen Inhalt in die Benutzeroberfläche zu laden, basierend auf dem Pfad der URL, zu der navigiert wird.scroll()
ermöglicht es Ihnen, das Scroll-Verhalten des Browsers manuell zu initiieren (z.B. zu einem Fragment-Identifikator in der URL), wenn es für Ihren Code sinnvoll ist, anstatt darauf zu warten, dass der Browser es automatisch behandelt.
Sobald eine Navigation eingeleitet und Ihr intercept()
Handler aufgerufen wurde, wird eine Instanz eines NavigationTransition
Objekts erstellt (zugänglich über Navigation.transition
), die verwendet werden kann, um den Prozess der laufenden Navigation zu verfolgen.
Hinweis: In diesem Kontext bezieht sich "transition" auf den Übergang zwischen einem Historieneintrag und einem anderen. Es hat keine Beziehung zu CSS-Übergängen.
Hinweis: Sie können auch preventDefault()
verwenden, um die Navigation vollständig zu stoppen, für die meisten Navigationstypen; die Stornierung von Traversierungen ist noch nicht implementiert.
Wenn das Versprechen der intercept()
Handler-Funktion erfüllt wird, wird das navigatesuccess
Ereignis des Navigation
Objekts ausgelöst, sodass Sie Bereinigungscode ausführen können, nachdem eine erfolgreiche Navigation abgeschlossen wurde. Wenn es abgelehnt wird, was bedeutet, dass die Navigation fehlgeschlagen ist, wird stattdessen navigateerror
ausgelöst, sodass Sie den Fehlerfall anmutig handhaben können. Es gibt auch eine finished
Eigenschaft am NavigationTransition
Objekt, die zu demselben Zeitpunkt erfüllt oder abgelehnt wird, an dem die oben genannten Ereignisse ausgelöst werden, und einen anderen Weg bietet, um die Erfolg- und Fehlerfälle zu handhaben.
Hinweis: Bevor die Navigation API verfügbar war, mussten Sie, um etwas Ähnliches zu tun, alle Klickereignisse auf Links abhören, e.preventDefault()
ausführen, den entsprechenden History.pushState()
Aufruf durchführen und dann die Seitenansicht basierend auf der neuen URL einrichten. Und das würde nicht alle Navigationen behandeln - nur benutzerinitiierte Linkklicks.
Programmatische Aktualisierung und Durchlaufen der Navigation-Historie
Wenn der Benutzer Ihre Anwendung durchläuft, wird bei jedem neuen Ort, zu dem navigiert wird, ein Eintrag in der Navigation-Historie erstellt. Jeder Historieneintrag wird durch eine eindeutige Instanz eines NavigationHistoryEntry
Objekts dargestellt. Diese enthalten mehrere Eigenschaften wie den Schlüssel, die URL und Informationen zum Status des Eintrags. Sie können den Eintrag, auf dem sich der Benutzer gerade befindet, mit Navigation.currentEntry
abrufen und ein Array aller vorhandenen Historieneinträge mit Navigation.entries()
. Jedes NavigationHistoryEntry
Objekt hat ein dispose
Ereignis, das ausgelöst wird, wenn der Eintrag nicht mehr Teil der Browser-Historie ist. Wenn der Benutzer zum Beispiel dreimal zurücknavigiert und dann nach vorne zu einem anderen Ort navigiert, werden diese drei Historieneinträge entsorgt.
Hinweis: Die Navigation API gibt nur die Historieneinträge im aktuellen Browserkontext frei, die denselben Ursprung wie die aktuelle Seite haben (z.B. keine Navigationen in eingebetteten <iframe>
s oder über Origin-Grenzen hinweg), und bietet eine genaue Liste aller vorherigen Historieneinträge nur für Ihre App. Dies macht das Durchlaufen der Historie zu einer viel weniger fragilen Angelegenheit als mit der älteren History API.
Das Navigation
Objekt enthält alle Methoden, die Sie benötigen, um die Navigation-Historie zu aktualisieren und durch sie hindurchzugehen:
-
Navigiert zu einer neuen URL und erstellt einen neuen Eintrag in der Navigation-Historie.
reload()
Experimentell-
Lädt den aktuellen Eintrag der Navigation-Historie neu.
back()
Experimentell-
Navigiert zum vorherigen Eintrag der Navigation-Historie, falls möglich.
forward()
Experimentell-
Navigiert zum nächsten Eintrag der Navigation-Historie, falls möglich.
traverseTo()
Experimentell-
Navigiert zu einem spezifischen Eintrag der Navigation-Historie, identifiziert durch seinen Schlüsselwert, der über die relevante Eigenschaft
NavigationHistoryEntry.key
des Eintrags abgerufen wird.
Jede dieser Methoden gibt ein Objekt zurück, das zwei Versprechen enthält — { committed, finished }
. Dies ermöglicht es der aufrufenden Funktion, darauf zu warten, weitere Aktionen zu ergreifen, bis:
committed
erfüllt ist, was bedeutet, dass sich die sichtbare URL geändert hat und ein neuerNavigationHistoryEntry
erstellt wurde.finished
erfüllt ist, was bedeutet, dass alle von Ihremintercept()
Handler zurückgegebenen Versprechen erfüllt sind. Dies entspricht der Erfüllung des VersprechensNavigationTransition.finished
, wenn dasnavigatesuccess
Ereignis ausgelöst wird, wie zuvor erwähnt.- eines der oben genannten Versprechen abgelehnt wird, was bedeutet, dass die Navigation aus irgendeinem Grund fehlgeschlagen ist.
Zustand
Die Navigation API ermöglicht es Ihnen, Zustand auf jedem Historieneintrag zu speichern. Dies sind vom Entwickler definierte Informationen - es kann alles Mögliche sein. Zum Beispiel könnten Sie einen visitCount
Eigenschaft speichern wollen, die die Anzahl der Besuche einer Ansicht aufzeichnet, oder ein Objekt, das mehrere Eigenschaften des UI-Zustands enthält, damit der Zustand wiederhergestellt werden kann, wenn ein Benutzer zu dieser Ansicht zurückkehrt.
Um den Zustand eines NavigationHistoryEntry
abzurufen, rufen Sie dessen getState()
Methode auf. Er ist anfänglich undefined
, aber wenn Statusinformationen auf dem Eintrag gesetzt werden, wird er die zuvor gesetzten Statusinformationen zurückgeben.
Das Setzen des Zustands ist etwas nuancierter. Sie können den Statuswert nicht abrufen und dann direkt aktualisieren - die Kopie, die auf dem Eintrag gespeichert ist, wird sich nicht ändern. Stattdessen aktualisieren Sie ihn, während Sie ein navigate()
oder reload()
durchführen - jede dieser Methoden nimmt optional ein Objektparameter-Optionen entgegen, welches eine state
Eigenschaft enthält, die den neuen Status enthält, der auf dem Historieneintrag festgelegt wird. Wenn diese Navigationen ausgeführt werden, wird die Statusänderung automatisch angewendet.
In einigen Fällen jedoch wird eine Statusänderung unabhängig von einer Navigation oder einem Reload sein - zum Beispiel, wenn eine Seite ein erweiterbares/zusammenklappbares <details>
Element enthält. In diesem Fall möchten Sie möglicherweise den erweiterten/zusammengeklappten Zustand in Ihrem Historieneintrag speichern, um ihn wiederherzustellen, wenn der Benutzer zur Seite zurückkehrt oder seinen Browser neu startet. Fälle wie diese werden mit Navigation.updateCurrentEntry()
behandelt. Der currententrychange
wird ausgelöst, wenn die aktuelle Eintragsänderung abgeschlossen ist.
Einschränkungen
Es gibt einige wahrgenommene Einschränkungen mit der Navigation API:
- Die aktuelle Spezifikation löst kein
navigate
Ereignis beim ersten Laden einer Seite aus. Dies könnte für Websites, die Server Side Rendering (SSR) verwenden, akzeptabel sein - Ihr Server könnte den korrekten Anfangszustand zurückgeben, was der schnellste Weg ist, um Inhalte an Ihre Benutzer zu liefern. Aber Websites, die clientseitigen Code nutzen, um ihre Seiten zu erstellen, benötigen möglicherweise eine zusätzliche Funktion, um die Seite zu initialisieren. - Die Navigation API wirkt sich nur auf einen einzigen Frame aus - die oberste Seite oder ein spezifisches
<iframe>
. Dies hat einige interessante Implikationen, die weiterhin in der Spezifikation dokumentiert sind, aber in der Praxis die Verwirrung bei Entwicklern reduzieren wird. Die vorherige History API hat mehrere verwirrende Randfälle, wie die Unterstützung von Frames, die die Navigation API von vornherein behandelt. - Sie können derzeit die Navigation API nicht nutzen, um die Historieliste programmgesteuert zu verändern oder umzustellen. Es könnte nützlich sein, einen temporären Zustand zu haben, zum Beispiel, um den Benutzer zu einem temporären Modal zu navigieren, das sie nach einigen Informationen fragt, und dann zur vorherigen URL zurückzugehen. In diesem Fall möchten Sie den temporären Modal-Navigationseintrag löschen, damit der Benutzer den Anwendungsfluss nicht stören kann, indem er die Vorwärtstaste drückt und ihn erneut öffnet.
Schnittstellen
-
Ereignisobjekt für das
navigate
Ereignis, das ausgelöst wird, wenn eine Art von Navigation eingeleitet wird. Es bietet Zugriff auf Informationen über diese Navigation, insbesondere auf dasintercept()
, welches es Ihnen ermöglicht zu kontrollieren, was passiert, wenn die Navigation eingeleitet wird. -
Ermöglicht die Steuerung aller Navigationsaktionen für das aktuelle
window
an einem zentralen Ort, einschließlich der programmgesteuerten Initiierung von Navigationen, der Untersuchung von Navigation-Historieneinträgen und der Verwaltung von Navigationen während sie passieren. -
Repräsentiert eine kürzlich erfolgte dokumentübergreifende Navigation. Sie enthält den Navigationstyp und aktuelle sowie Ziel-Dokumenthistorieneinträge.
-
Ereignisobjekt für das
currententrychange
Ereignis, das ausgelöst wird, wenn sich derNavigation.currentEntry
geändert hat. Es bietet Zugriff auf den Navigationstyp und den vorherigen Historieneintrag, von dem aus navigiert wurde. -
Repräsentiert das Ziel, zu dem in der aktuellen Navigation navigiert wird.
-
Repräsentiert einen einzelnen Navigation-Historieneintrag.
-
Repräsentiert eine laufende Navigation.
Erweiterungen zu anderen Schnittstellen
-
Gibt das mit dem aktuellen
window
assoziierteNavigation
Objekt zurück. Dies ist der Einstiegspunkt für die Navigation API.
Beispiele
Hinweis: Schauen Sie sich Domenic Denicola's Navigation API live demo an.
Umgang mit einer Navigation mit intercept()
navigation.addEventListener("navigate", (event) => {
// Exit early if this navigation shouldn't be intercepted,
// e.g. if the navigation is cross-origin, or a download request
if (shouldNotIntercept(event)) {
return;
}
const url = new URL(event.destination.url);
if (url.pathname.startsWith("/articles/")) {
event.intercept({
async handler() {
// The URL has already changed, so show a placeholder while
// fetching the new content, such as a spinner or loading page
renderArticlePagePlaceholder();
// Fetch the new content and display when ready
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
},
});
}
});
Umgang mit dem Scrollen mit scroll()
In diesem Beispiel des Abfangens einer Navigation beginnt die handler()
Funktion damit, einige Artikelinhalte abzurufen und zu rendern, aber dann mit dem Abrufen und Rendern von zusätzlichem Inhalt fortzufahren. Es macht Sinn, die Seite so schnell wie möglich zum Hauptartikelinhalt zu scrollen, damit der Benutzer mit ihm interagieren kann, anstatt darauf zu warten, dass auch der zusätzliche Inhalt gerendert wird. Um dies zu erreichen, haben wir einen scroll()
Aufruf zwischen den beiden hinzugefügt.
navigation.addEventListener("navigate", (event) => {
if (shouldNotIntercept(event)) {
return;
}
const url = new URL(event.destination.url);
if (url.pathname.startsWith("/articles/")) {
event.intercept({
async handler() {
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
event.scroll();
const secondaryContent = await getSecondaryContent(url.pathname);
addSecondaryContent(secondaryContent);
},
});
}
});
Durchlaufen zu einem bestimmten Historieneintrag
// On JS startup, get the key of the first loaded page
// so the user can always go back there.
const { key } = navigation.currentEntry;
backToHomeButton.onclick = () => navigation.traverseTo(key);
// Navigate away, but the button will always work.
await navigation.navigate("/another_url").finished;
Aktualisierung des Zustands
navigation.navigate(url, { state: newState });
Oder
navigation.reload({ state: newState });
Oder wenn der Zustand unabhängig von einer Navigation oder einem Reload ist:
navigation.updateCurrentEntry({ state: newState });
Spezifikationen
Specification |
---|
HTML Standard # navigation-api |
Browser-Kompatibilität
api.Navigation
BCD tables only load in the browser
api.NavigationDestination
BCD tables only load in the browser
api.NavigationHistoryEntry
BCD tables only load in the browser
api.NavigationTransition
BCD tables only load in the browser