Signatur
Beschreibung
NavigateEvent ist das Ereignisobjekt, das dem Handler des navigate-Ereignisses auf window.navigation übergeben wird. Das Ereignis wird bei jeder Art von Navigation im aktuellen Dokument ausgelöst: bei Klicks auf Links, beim Absenden von Formularen, bei location.href-Zuweisungen, bei history.pushState()/replaceState(), bei navigation.navigate(), bei Vor/Zurück im Browser und bei Änderungen des Fragments (#hash). Damit gibt es für Single-Page-Anwendungen einen einzigen, zentralen Ort für das Routing statt verstreuter click- und popstate-Handler.
Die wichtigsten Eigenschaften sind:
destination– einNavigationDestinationmiturl,key,id,index,sameDocumentundgetState().navigationType–"push","replace","reload"oder"traverse".canIntercept– ob die Navigation mitintercept()in eine Navigation im selben Dokument umgewandelt werden darf (z. B.falsebei fremden Origins).hashChange,downloadRequest,formData,userInitiated,info,hasUAVisualTransition,sourceElement– Zusatzinformationen über Art und Auslöser der Navigation.signal– einAbortSignal, das abgebrochen wird, wenn die Navigation abgebrochen oder durch eine neue ersetzt wird.
Mit den Methoden intercept(options) und scroll() steuert man die Navigation: intercept() verhindert das Laden eines neuen Dokuments, aktualisiert die URL sofort und führt einen (asynchronen) handler aus, in dem man die neue Ansicht rendert. Der Browser zeigt währenddessen den Ladezustand an, verwaltet Fokus und Scroll-Position und löst anschließend navigatesuccess bzw. navigateerror aus. Mit scroll() kann die Scroll-Wiederherstellung manuell ausgelöst werden, wenn scroll: "manual" gesetzt wurde.
Wie jedes Event unterstützt NavigateEvent auch preventDefault(): Ist cancelable wahr, wird die Navigation dadurch komplett abgebrochen (z. B. um ungespeicherte Änderungen zu schützen). Bei "traverse"-Navigationen ist das nur eingeschränkt möglich.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Konstruktor-Parameter: Name des Ereignisses, in der Praxis "navigate". |
|
| $eventInit Pflicht | object | Konstruktor-Parameter mit den Feldern destination (Pflicht, NavigationDestination), navigationType, canIntercept, userInitiated, hashChange, signal (Pflicht), formData, downloadRequest, info, hasUAVisualTransition, sourceElement sowie den üblichen EventInit-Feldern. |
|
| $intercept(options.handler) | () => Promise<void> | Asynchrone Funktion, die die neue Ansicht rendert. Das zurückgegebene Promise bestimmt, wann die Navigation als abgeschlossen gilt. | |
| $intercept(options.focusReset) | "after-transition" | "manual" | "after-transition" | Ob der Browser den Fokus nach Abschluss des Handlers zurücksetzt (auf das erste Element mit autofocus bzw. den body). |
| $intercept(options.scroll) | "after-transition" | "manual" | "after-transition" | Ob der Browser nach dem Handler automatisch scrollt (zum Fragment, nach oben oder zur gespeicherten Position). Bei "manual" ruft man selbst event.scroll() auf. |
| $intercept(options.precommitHandler) | (controller) => Promise<void> | Neuere Erweiterung (bisher nur Chromium): läuft bevor die URL übernommen wird, z. B. für Weiterleitungen über controller.redirect(). |
Beispiele
Zentrales SPA-Routing mit intercept()
const routes = {
'/': () => '<h1>Start</h1>',
'/about': () => '<h1>Über uns</h1>'
};
navigation.addEventListener('navigate', (event) => {
// Nur abfangen, was wir auch dürfen und wollen
if (!event.canIntercept || event.hashChange || event.downloadRequest !== null) return;
const url = new URL(event.destination.url);
const render = routes[url.pathname];
if (!render) return; // unbekannte Route: normale Navigation
event.intercept({
async handler() {
document.querySelector('main').innerHTML = render();
console.log(`${event.navigationType} → ${url.pathname}`);
}
});
});
Daten laden und bei Abbruch mit signal stoppen
navigation.addEventListener('navigate', (event) => {
const url = new URL(event.destination.url);
if (!event.canIntercept || !url.pathname.startsWith('/artikel/')) return;
event.intercept({
scroll: 'manual',
async handler() {
const id = url.pathname.split('/').pop();
// signal bricht den fetch ab, wenn der Nutzer weiter navigiert
const res = await fetch(`/api/artikel/${id}`, { signal: event.signal });
const artikel = await res.json();
document.querySelector('main').textContent = artikel.titel;
event.scroll(); // Scrollen erst, wenn der Inhalt da ist
}
});
});
navigation.addEventListener('navigateerror', (e) => {
console.warn('Navigation fehlgeschlagen:', e.message);
});
Navigation bei ungespeicherten Änderungen verhindern
let ungespeichert = true;
navigation.addEventListener('navigate', (event) => {
if (ungespeichert && event.cancelable && event.navigationType !== 'reload') {
if (!confirm('Änderungen verwerfen?')) {
event.preventDefault();
console.log('Navigation abgebrochen');
}
}
});
Informationen über navigate() mitgeben und auswerten
navigation.addEventListener('navigate', (event) => {
console.log(event.navigationType, event.info, event.userInitiated);
console.log(event.destination.getState());
if (event.canIntercept) event.intercept({ handler: async () => {} });
});
await navigation.navigate('/profil', {
state: { tab: 'einstellungen' },
info: { animation: 'slide-left' }
}).finished;