Start · Sprachen · JavaScript · Referenz · NavigateEvent.intercept()

NavigateEvent.intercept()

Methode

Fängt eine Navigation im <code>navigate</code>-Event ab und macht daraus eine Navigation im selben Dokument zur Ziel-URL. Die Seite wird dabei nicht neu geladen.

seit JavaScript Navigation API: Chromium 102+ (Chrome, Edge, Opera Kategorie: webapi

Signatur

NavigateEvent.prototype.intercept(options)

Beschreibung

intercept() ist der zentrale Baustein für clientseitiges Routing mit der Navigation API. Sie rufen die Methode im Listener für das navigate-Event von window.navigation auf. Der Browser lädt dann kein neues Dokument. Stattdessen aktualisiert er die URL auf event.destination.url, legt einen neuen Verlaufseintrag an (bzw. ersetzt oder wechselt ihn) und führt Ihren handler aus. Dort rendern Sie den neuen Inhalt.

Anders als bei history.pushState() und dem Abfangen von click-Events auf Links erfasst ein einziger Listener alle Arten von Navigation: Linkklicks, Formularversand, Zurück/Vor-Tasten und programmatische Aufrufe wie navigation.navigate(). Der Browser zeigt außerdem einen Ladeindikator an, solange das Promise des Handlers aussteht. Er kümmert sich auch um die Wiederherstellung der Scrollposition und das Zurücksetzen des Fokus.

Ob eine Navigation abgefangen werden darf, zeigt event.canIntercept. Navigationen zu einem anderen Ursprung (Cross-Origin) und bestimmte Traversal-Fälle lassen sich nicht abfangen. Für reine Sprünge zu Ankern (event.hashChange) oder Downloads (event.downloadRequest) ist ein Abfangen oft nicht sinnvoll.

Ist der Handler erfolgreich, feuert navigation das Event navigatesuccess. Wird das Promise abgelehnt, feuert navigateerror. Das Promise finished des Aufrufs von navigation.navigate() verhält sich genauso.

Parameter

Name Typ Default Beschreibung
$options object {} Optionales Konfigurationsobjekt mit folgenden Eigenschaften.
$options.handler () => Promise<void> | void Callback, der den neuen Inhalt lädt und darstellt. Er läuft, nachdem die URL aktualisiert wurde. Gibt er ein Promise zurück, gilt die Navigation erst als abgeschlossen, wenn dieses erfüllt ist.
$options.focusReset "after-transition" | "manual" "after-transition" Mit "after-transition" setzt der Browser den Fokus nach Abschluss des Handlers auf das erste Element mit autofocus oder auf <body> zurück. Mit "manual" steuern Sie den Fokus selbst.
$options.scroll "after-transition" | "manual" "after-transition" Mit "after-transition" scrollt der Browser nach Abschluss des Handlers automatisch: bei Traversal oder Reload zur gespeicherten Position, sonst an den Seitenanfang oder zum Fragment. Mit "manual" lösen Sie das Scrollen selbst aus, z. B. mit event.scroll().
$options.precommitHandler (controller: NavigationPrecommitController) => Promise<void> Neuere, noch nicht überall verfügbare Option. Der Callback läuft bevor die URL übernommen wird, etwa um Daten vorab zu laden oder mit controller.redirect() umzuleiten. Nur bei abbrechbaren Navigationen (event.cancelable) erlaubt.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Den Erfolg verfolgen Sie über navigatesuccess/navigateerror oder über die Promises committed/finished von navigation.navigate().

Beispiele

Einfacher SPA-Router

// Alle Navigationen innerhalb derselben Origin abfangen
navigation.addEventListener('navigate', (event) => {
  // Nicht abfangbare Navigationen, Anker-Sprünge und Downloads dem Browser überlassen
  if (!event.canIntercept || event.hashChange || event.downloadRequest !== null) {
    return;
  }

  const url = new URL(event.destination.url);

  if (url.pathname.startsWith('/artikel/')) {
    event.intercept({
      async handler() {
        const res = await fetch(`/api${url.pathname}`, { signal: event.signal });
        const artikel = await res.json();
        document.querySelector('main').textContent = artikel.titel;
        document.title = artikel.titel;
      },
    });
  }
});

Scrollen und Fokus selbst steuern

navigation.addEventListener('navigate', (event) => {
  if (!event.canIntercept) return;

  event.intercept({
    scroll: 'manual',
    focusReset: 'manual',
    async handler() {
      const main = document.querySelector('main');
      main.innerHTML = '<p>Lade …</p>';

      const html = await fetch(event.destination.url, { signal: event.signal })
        .then((r) => r.text());
      main.innerHTML = new DOMParser()
        .parseFromString(html, 'text/html')
        .querySelector('main').innerHTML;

      // Erst scrollen, wenn der Inhalt da ist
      event.scroll();
      main.querySelector('h1')?.focus();
    },
  });
});

Erfolg und Fehler auswerten

navigation.addEventListener('navigate', (event) => {
  if (!event.canIntercept) return;
  event.intercept({
    async handler() {
      const res = await fetch(event.destination.url, { signal: event.signal });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
    },
  });
});

navigation.addEventListener('navigatesuccess', () => {
  console.log('Navigation abgeschlossen:', navigation.currentEntry.url);
});

navigation.addEventListener('navigateerror', (e) => {
  console.error('Navigation fehlgeschlagen:', e.message);
});

// Programmatisch navigieren und auf das Ende warten
const { finished } = navigation.navigate('/profil');
await finished;
Navigation abgeschlossen: https://example.com/profil

// Wichtig · Fallstricke

  • Synchron aufrufen: intercept() muss während des Event-Dispatchs aufgerufen werden, also nicht nach einem await im Listener. Sonst wirft die Methode einen InvalidStateError. Den gleichen Fehler gibt es, wenn das Event bereits mit preventDefault() abgebrochen wurde.
  • canIntercept prüfen: Ist event.canIntercept false (z. B. bei Cross-Origin-Zielen) oder ist das Event nicht vertrauenswürdig (isTrusted === false), wirft die Methode einen SecurityError.
  • Abbruch beachten: Startet der Nutzer während des Handlers eine neue Navigation, wird event.signal abgebrochen. Geben Sie das Signal an fetch() weiter, damit veraltete Antworten nicht den neuen Inhalt überschreiben.
  • Sie können intercept() mehrfach aufrufen, auch aus verschiedenen Listenern. Alle Handler laufen dann parallel, und die Navigation ist erst abgeschlossen, wenn alle fertig sind.
  • Bei Traversal zu einem anderen Dokument lässt sich die Navigation nicht abfangen. Innerhalb desselben Dokuments ist ein Zurück/Vor zwar abfangbar, aber nicht mit preventDefault() abbrechbar.
  • Kompatibilität: Die Navigation API gibt es seit Chromium 102. Safari und Firefox unterstützen sie erst in neueren Versionen. Prüfen Sie die Unterstützung mit 'navigation' in window und greifen Sie sonst auf die History-API zurück. precommitHandler ist noch deutlich weniger verbreitet.
  • Sicherheit: Wenn Sie abgerufenes HTML mit innerHTML einsetzen, droht XSS. Verwenden Sie nur vertrauenswürdige Quellen oder bereinigen Sie das HTML vorher.