Start · Sprachen · JavaScript · Referenz · Window: hashchange

Window: hashchange

Ereignis

Wird am <code>window</code> ausgelöst, wenn sich der Fragmentbezeichner der URL (der Teil ab <code>#</code>) ändert.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

window.addEventListener("hashchange", handler)

Beschreibung

Das hashchange-Event feuert am Window-Objekt, sobald sich der Hash-Anteil der aktuellen URL ändert. Das passiert z. B. durch einen Klick auf einen Link wie <a href="#kontakt">, durch Setzen von location.hash oder durch Vor- und Zurück-Navigation zwischen Einträgen, die sich nur im Hash unterscheiden. Die Seite wird dabei nicht neu geladen.

Der Handler bekommt ein HashChangeEvent mit den Eigenschaften oldURL und newURL, beide als vollständige URL-Strings. Registrieren kannst du ihn mit window.addEventListener("hashchange", handler) oder über die Eigenschaft window.onhashchange = handler. Das Event lässt sich nicht abbrechen und steigt nicht auf (kein Bubbling).

Klassisch dient hashchange für einfaches clientseitiges Routing (Hash-Routing), etwa in Single-Page-Apps ohne Server-Konfiguration, für Tabs oder Akkordeons, deren Zustand in der URL landen soll, und für Deep-Links auf Abschnitte.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Event-Name "hashchange".
$handler Pflicht (event: HashChangeEvent) => void Callback, der ein HashChangeEvent mit oldURL und newURL erhält.
$options boolean | AddEventListenerOptions false Optionen wie once, signal oder passive.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt undefined zurück. Der Handler bekommt ein HashChangeEvent.

Beispiele

Alte und neue URL protokollieren

window.addEventListener("hashchange", (event) => {
  console.log("Von:", event.oldURL);
  console.log("Nach:", event.newURL);
});

// Hash-Wechsel per Code auslösen
location.hash = "#kontakt";
Von: https://example.com/ Nach: https://example.com/#kontakt

Einfacher Hash-Router

const routes = {
  "": () => "<h1>Startseite</h1>",
  "about": () => "<h1>Über uns</h1>",
  "kontakt": () => "<h1>Kontakt</h1>"
};

const render = () => {
  const route = decodeURIComponent(location.hash.slice(1));
  const view = routes[route] ?? (() => "<h1>404 – nicht gefunden</h1>");
  document.querySelector("#app").innerHTML = view();
};

window.addEventListener("hashchange", render);
// Beim ersten Laden feuert hashchange nicht – also direkt rendern
window.addEventListener("DOMContentLoaded", render);

on-Property und Entfernen des Listeners

// Variante 1: on-Property (überschreibt einen vorhandenen Handler)
window.onhashchange = () => console.log("Hash jetzt:", location.hash);

// Variante 2: benannter Handler, der sich wieder entfernen lässt
const onTabChange = () => {
  const tab = location.hash.slice(1) || "uebersicht";
  document.querySelectorAll("[data-tab]").forEach((el) => {
    el.hidden = el.dataset.tab !== tab;
  });
};

window.addEventListener("hashchange", onTabChange);

// Später, z. B. beim Abbau der Komponente:
window.removeEventListener("hashchange", onTabChange);
window.onhashchange = null;
Hash jetzt: #einstellungen

// Wichtig · Fallstricke

  • Kein Event beim Laden der Seite: Wenn die Seite schon mit einem Hash geöffnet wird, feuert hashchange nicht. Den Anfangszustand musst du selbst auswerten, z. B. in DOMContentLoaded.
  • Nur echte Änderungen zählen: Setzt du location.hash auf den Wert, den der Hash schon hat, wird kein Event ausgelöst.
  • history.pushState() und replaceState() lösen kein hashchange aus, auch wenn sich dabei der Hash ändert. Vor- und Zurück-Navigation zwischen Hash-Einträgen löst dagegen sowohl popstate als auch hashchange aus.
  • Sicherheit: Der Hash stammt vom Nutzer und kann beliebig manipuliert werden. Füge ihn nie ungeprüft per innerHTML ins DOM ein, sonst droht DOM-basiertes XSS. Gleiche ihn stattdessen mit einer festen Liste erlaubter Routen ab oder nutze textContent.
  • Kodierung: location.hash kann prozentkodiert sein. Nutze decodeURIComponent(), bevor du den Wert vergleichst.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt (auch schon von IE8+). oldURL und newURL gibt es im IE nicht.