Signatur
Beschreibung
Der Konstruktor PopStateEvent() erzeugt ein Ereignisobjekt vom Typ PopStateEvent. Normalerweise erzeugt der Browser solche Ereignisse selbst, wenn sich der aktive History-Eintrag ändert, etwa durch die Zurück-/Vor-Schaltfläche oder durch history.back(), history.forward() und history.go(). Dabei landet der zuvor mit history.pushState() bzw. history.replaceState() gespeicherte Zustand in der Eigenschaft event.state.
Selbst gebraucht wird der Konstruktor vor allem in zwei Fällen:
- Client-seitiges Routing:
history.pushState()löst keinpopstate-Ereignis aus. Soll ein Router, der nur aufpopstatehört, nach einer programmatischen Navigation trotzdem reagieren, kann man ein eigenesPopStateEventanwindowsenden. - Tests: In Unit- oder Integrationstests (z. B. mit jsdom) lässt sich eine Zurück-Navigation simulieren, ohne dass die echte History benutzt werden muss.
Ein von Hand erzeugtes Ereignis ändert weder die URL noch den Wert von history.state. Es wird nur an die registrierten Listener ausgeliefert. Seine Eigenschaft isTrusted ist immer false.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses, wird nicht nach Groß-/Kleinschreibung unterschieden. In der Praxis fast immer "popstate". |
|
| $options | object | {} | Optionales Objekt mit den Feldern aus EventInit (bubbles, cancelable, composed, jeweils standardmäßig false) und zusätzlich state. |
| $options.state | any | null | Beliebiger Wert, den Listener über event.state auslesen können. Das ist typischerweise dasselbe Objekt, das an pushState() übergeben wurde. |
| $options.hasUAVisualTransition | boolean | false | Gibt an, ob der Browser bereits einen eigenen visuellen Übergang gezeigt hat (z. B. eine Wischgeste). Wird nur von neueren Chromium-Versionen unterstützt. |
Rückgabewert
PopStateEvent-Objekt, das sich mit EventTarget.dispatchEvent() auslösen lässt.Beispiele
Ereignis erzeugen und Eigenschaften prüfen
const event = new PopStateEvent('popstate', {
state: { page: 2, filter: 'neu' }
});
console.log(event.type); // Ereignisname
console.log(event.state.page); // übergebener Zustand
console.log(event.bubbles); // Standardwert
console.log(event.isTrusted); // selbst erzeugt
Router nach pushState() benachrichtigen
// Einfacher Router, der nur auf popstate hört
const render = (state) => {
document.querySelector('#app').textContent =
`Ansicht: ${state?.view ?? 'start'}`;
};
window.addEventListener('popstate', (e) => render(e.state));
// Programmatische Navigation – pushState allein löst kein popstate aus
const navigate = (url, state) => {
history.pushState(state, '', url);
window.dispatchEvent(new PopStateEvent('popstate', { state }));
};
navigate('/profil', { view: 'profil' });
Zurück-Navigation im Test simulieren
const log = [];
const onPop = (e) => log.push(e.state?.step ?? 'kein Zustand');
window.addEventListener('popstate', onPop);
// Zurück-Schaltfläche nachstellen
window.dispatchEvent(new PopStateEvent('popstate', { state: { step: 1 } }));
window.dispatchEvent(new PopStateEvent('popstate')); // state = null
window.removeEventListener('popstate', onPop);
console.log(log);
// Wichtig · Fallstricke
- Keine echte Navigation: Wenn Sie das Ereignis selbst auslösen, ändern sich weder
locationnochhistory.state. Wer URL und Zustand zusammenhalten will, muss vorherpushState()bzw.replaceState()aufrufen. - Standardwert von
state: Wirdstatenicht angegeben, istevent.stategleichnull. Listener sollten deshalb mit optionaler Verkettung (e.state?.x) darauf zugreifen. - Keine Kopie: Anders als bei
pushState()wird der Zustand hier nicht mit dem Structured-Clone-Algorithmus kopiert. Listener bekommen dieselbe Objektreferenz und können sie verändern. isTrustedistfalse: Code, der nur echte Browser-Ereignisse zulässt, ignoriert selbst ausgelöste Ereignisse.- Kompatibilität: Der Konstruktor wird von allen modernen Browsern unterstützt, der Internet Explorer kennt ihn nicht (dort war
document.createEvent('PopStateEvent')nötig).hasUAVisualTransitiongibt es bislang nur in Chromium-Browsern. - Alternative: Für neue Router lohnt sich ein Blick auf die Navigation-API (
navigation.addEventListener('navigate', …)). Sie erkennt auch programmatische Navigation. Die Browser-Unterstützung ist dort aber noch lückenhaft.