history. pushState()
Dodaje nowy wpis do historii przeglądarki i zmienia adres w pasku bez przeładowania strony.
- Zwraca
undefined
Przykład
#function showLesson(number) {
document.querySelector('#title').textContent = `Lekcja ${number}`
}
function goToLesson(number) {
showLesson(number)
history.pushState({ lesson: number }, '', `/kursy/javascript/lekcja-${number}`)
}
goToLesson(6)
console.log(location.pathname)
console.log(history.state)/kursy/javascript/lekcja-6
{ lesson: 6 }W izolowanej ramce podglądu zmiana adresu jest zablokowana (SecurityError), dlatego przykład nie uruchamia się tutaj. Na zwykłej stronie adres w pasku zmienia się na /kursy/javascript/lekcja-6, a strona się nie przeładowuje.
Definicja i zastosowanie
#Metoda history.pushState() zmienia adres widoczny w pasku przeglądarki i dodaje nowy wpis do historii karty, ale nie przeładowuje strony i niczego nie pobiera z serwera. Na tym opierają się aplikacje jednostronicowe (SPA): treść zmieniasz JavaScriptem, a adres nadąża za tym, co widzi użytkownik, więc można go skopiować, dodać do zakładek albo odświeżyć.
Pierwszy argument to dane (stan) związane z wpisem, np. { lesson: 5 }. Muszą dać się sklonować, tak jak w structuredClone(), więc funkcje i elementy DOM odpadają. Drugi argument przeglądarki ignorują, ale trzeba go podać, zwykle jako pusty napis. Trzeci to nowy adres: może być względny, ale musi należeć do tej samej domeny (origin), inaczej metoda rzuci błąd.
Gdy użytkownik kliknie „Wstecz” lub „Dalej”, przeglądarka wywoła na window zdarzenie popstate i przekaże w event.state dane zapisane przy wpisie. Twoim zadaniem jest wtedy pokazać odpowiednią treść. Samo pushState() nie wywołuje zdarzenia popstate.
Siostrzana metoda history.replaceState() przyjmuje te same argumenty, ale podmienia bieżący wpis, zamiast dodawać nowy. Przydaje się np. przy zmianie filtrów, które nie powinny zapełniać historii. Pamiętaj, że po odświeżeniu strony przeglądarka poprosi serwer o nowy adres, więc serwer musi umieć go obsłużyć.
Składnia
#history.pushState(state, unused)
history.pushState(state, unused, url)
history.replaceState(state, unused, url)
history.state
window.addEventListener("popstate", listener)Parametry
#state
dowolna wartość do sklonowania
Dane zapisane przy wpisie historii. Wrócą wevent.statezdarzeniapopstatei whistory.state.unused
napis
Parametr zachowany z powodów historycznych. Podaj pusty napis"".url
opcjonalny, napis lub URL
Nowy adres, względny albo bezwzględny, z tej samej domeny co strona. Bez niego adres się nie zmienia.
Więcej przykładów
#const title = document.querySelector('#title')
function render(lesson) {
title.textContent = `Lekcja ${lesson}`
console.log(`Pokazuję lekcję ${lesson}`)
}
window.addEventListener('popstate', (event) => {
render(event.state?.lesson ?? 1)
})
history.pushState({ lesson: 6 }, '', '/kursy/javascript/lekcja-6')
render(6)
history.pushState({ lesson: 7 }, '', '/kursy/javascript/lekcja-7')
render(7)
history.back()Pokazuję lekcję 6 Pokazuję lekcję 7 Pokazuję lekcję 6
history.back() działa jak kliknięcie „Wstecz”: przeglądarka wraca do poprzedniego wpisu i wywołuje zdarzenie popstate z zapisanym stanem { lesson: 6 }. Strona się nie przeładowuje, a treść odtwarza funkcja render().
function applyFilter(level) {
const url = new URL(location.href)
url.searchParams.set('poziom', level)
history.replaceState(null, '', url)
console.log(location.search)
}
applyFilter('początkujący')
applyFilter('średni')?poziom=pocz%C4%85tkuj%C4%85cy ?poziom=%C5%9Bredni
Każde wywołanie podmienia bieżący wpis historii, więc „Wstecz” nie przechodzi przez kolejne filtry, tylko wraca do poprzedniej strony. Wynik dotyczy strony, która na początku nie miała parametrów w adresie.
Obsługa przeglądarek
#Szeroko dostępne
Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.
- Chrome
- Edge
- Firefox
- Safari
Dobre praktyki
#- Po
pushState()zawsze obsłuż zdarzeniepopstate. Bez tego przycisk „Wstecz” zmieni adres, ale treść strony zostanie stara. - Zapisuj w stanie tylko proste dane, np. identyfikator lekcji. Funkcje i elementy DOM nie dają się sklonować i spowodują błąd
DataCloneError. - Upewnij się, że serwer obsługuje adresy tworzone przez
pushState(). Po odświeżeniu strony albo wejściu z zakładki przeglądarka poprosi o nie serwer.
Powiązane hasła
#- locationObiekt z informacjami o adresie bieżącej strony. Pozwala odczytać jego części i przejść pod inny adres.
- URLObiekt do tworzenia, odczytywania i zmieniania adresów URL. Rozkłada adres na części: protokół, host, ścieżkę i parametry.
- URLSearchParamsObiekt do odczytu i budowania parametrów zapytania w adresie, czyli części po znaku ?, np. ?kurs=js&strona=2.
- EventTarget.addEventListener()Rejestruje funkcję wywoływaną za każdym razem, gdy na elemencie wystąpi zdarzenie, np. kliknięcie.
- structuredClone()Tworzy głęboką kopię wartości, łącznie z zagnieżdżonymi obiektami, datami, Map i Set.
Widzisz błąd albo brakuje przykładu? Napisz do nas.