history.pushState()

Dodaje nowy wpis do historii przeglądarki i zmienia adres w pasku bez przeładowania strony.

Zwraca
undefined
Na tej stronie

Przykład

#
JavaScript
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)
Wynik
/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

#
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ą w event.state zdarzenia popstate i w history.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

#
Obsługa przycisku Wstecz przez popstate
JavaScript
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()
Wynik
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().

replaceState() przy zmianie filtrów
JavaScript
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')
Wynik
?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ż zdarzenie popstate. 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

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.