Signatur
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
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";
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;
// Wichtig · Fallstricke
- Kein Event beim Laden der Seite: Wenn die Seite schon mit einem Hash geöffnet wird, feuert
hashchangenicht. Den Anfangszustand musst du selbst auswerten, z. B. inDOMContentLoaded. - Nur echte Änderungen zählen: Setzt du
location.hashauf den Wert, den der Hash schon hat, wird kein Event ausgelöst. history.pushState()undreplaceState()lösen keinhashchangeaus, auch wenn sich dabei der Hash ändert. Vor- und Zurück-Navigation zwischen Hash-Einträgen löst dagegen sowohlpopstateals auchhashchangeaus.- Sicherheit: Der Hash stammt vom Nutzer und kann beliebig manipuliert werden. Füge ihn nie ungeprüft per
innerHTMLins DOM ein, sonst droht DOM-basiertes XSS. Gleiche ihn stattdessen mit einer festen Liste erlaubter Routen ab oder nutzetextContent. - Kodierung:
location.hashkann prozentkodiert sein. NutzedecodeURIComponent(), bevor du den Wert vergleichst. - Kompatibilität: Wird von allen modernen Browsern unterstützt (auch schon von IE8+).
oldURLundnewURLgibt es im IE nicht.