Signatur
Beschreibung
Das navigate-Ereignis des Navigation-Interfaces ist die zentrale Stelle, an der eine Single-Page-Application alle Navigationen der Seite beobachten und übernehmen kann: Link-Klicks, abgeschickte Formulare, location.href-Zuweisungen, history.pushState(), navigation.navigate() sowie die Vor- und Zurück-Schaltflächen des Browsers. Der Handler bekommt ein NavigateEvent übergeben.
Die wichtigste Methode ist event.intercept({ handler }). Damit wird aus einer normalen Dokument-Navigation eine Navigation innerhalb desselben Dokuments: Der Browser aktualisiert die URL und den Verlaufseintrag, lädt die Seite aber nicht neu. Stattdessen wird der übergebene asynchrone handler ausgeführt, der den neuen Inhalt darstellt. Solange das zurückgegebene Promise noch nicht erfüllt ist, zeigt der Browser einen Ladeindikator an. Außerdem kümmert er sich um Fokus und Scroll-Position.
Nützliche Eigenschaften des Ereignisses sind unter anderem destination.url (Ziel-URL), navigationType ("push", "replace", "reload", "traverse"), canIntercept, hashChange, downloadRequest, formData, userInitiated und signal. Das signal ist ein AbortSignal, das ausgelöst wird, wenn die Navigation abgebrochen oder durch eine neue ersetzt wird. Mit event.preventDefault() lässt sich eine Navigation ganz unterbinden, sofern cancelable auf true steht.
Statt addEventListener kann man auch die Eigenschaft navigation.onnavigate setzen. Ein Handler, der so zugewiesen wird, ersetzt allerdings jeden vorher zugewiesenen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses: "navigate". |
|
| $handler Pflicht | (event: NavigateEvent) => void | Callback, das ein NavigateEvent erhält. Es darf event.intercept() oder event.preventDefault() nur synchron aufrufen. |
|
| $options | boolean | AddEventListenerOptions | false | Übliche Listener-Optionen wie once, signal oder capture. |
Rückgabewert
addEventListener gibt nichts zurück. Die Navigation wird über das NavigateEvent-Objekt gesteuert.Beispiele
SPA-Routing mit intercept()
const renderPage = async (url, signal) => {
const res = await fetch(`/partials${url.pathname}`, { signal });
document.querySelector('main').innerHTML = await res.text();
};
navigation.addEventListener('navigate', (event) => {
// Nur abfangen, wenn es erlaubt und sinnvoll ist
if (!event.canIntercept || event.hashChange || event.downloadRequest !== null) return;
const url = new URL(event.destination.url);
if (!url.pathname.startsWith('/app/')) return; // normale Navigation
event.intercept({
async handler() {
await renderPage(url, event.signal);
}
});
});
Navigation bei ungespeicherten Änderungen verhindern (onnavigate)
let hasUnsavedChanges = true;
navigation.onnavigate = (event) => {
if (hasUnsavedChanges && event.cancelable && event.navigationType !== 'reload') {
const ok = confirm('Ungespeicherte Änderungen verwerfen?');
if (!ok) event.preventDefault();
}
};
// Später wieder entfernen
// navigation.onnavigate = null;
Navigationen protokollieren und Listener entfernen
const logNavigation = (event) => {
console.log(event.navigationType, event.destination.url, {
userInitiated: event.userInitiated,
sameDocument: event.destination.sameDocument
});
};
navigation.addEventListener('navigate', logNavigation);
// Programmgesteuerte Navigation löst das Ereignis ebenfalls aus
navigation.navigate('/app/profil');
// Nach Bedarf abmelden
navigation.removeEventListener('navigate', logNavigation);
Formular-Absendung abfangen
navigation.addEventListener('navigate', (event) => {
if (!event.formData || !event.canIntercept) return;
event.intercept({
async handler() {
const res = await fetch(event.destination.url, {
method: 'POST',
body: event.formData,
signal: event.signal
});
const { message } = await res.json();
document.querySelector('#status').textContent = message;
}
});
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Die Navigation-API gibt es seit Chrome/Edge 102 und Opera 88, in Firefox seit Version 147 und in Safari seit 26.2. Ältere Browser kennen sie nicht. Deshalb vorher mit
if ('navigation' in window)prüfen und sonst aufpopstatebzw. Klick-Handler zurückfallen. intercept()undpreventDefault()müssen synchron im Handler aufgerufen werden. Nach einemawaitist das nicht mehr möglich.intercept()funktioniert nur, wenncanInterceptauftruesteht. Bei ursprungsübergreifenden (Cross-Origin-)Zielen ist das nicht der Fall, dann wird einSecurityErrorgeworfen. Deshalb immer vorhercanInterceptprüfen.- Zurück-/Vor-Navigationen (
navigationType === "traverse") lassen sich mitpreventDefault()nur verhindern, wenn sie innerhalb desselben Dokuments stattfinden, die Seite selbst sie ausgelöst hat oder eine Nutzeraktivierung vorliegt. Sonst istcancelablefalse. - Das Ereignis wird nur für Navigationen im eigenen Browsing-Kontext ausgelöst. Navigationen in iframes oder anderen Fenstern bekommt man nicht mit.
event.signalanfetch()weiterreichen. So werden veraltete Anfragen abgebrochen, wenn der Nutzer schnell hintereinander navigiert.- Wer abgerufenes HTML per
innerHTMLeinfügt, muss sich gegen XSS schützen: nur vertrauenswürdige Quellen verwenden oder den Inhalt bereinigen.