История браузера. Объект history в JavaScript
На этом уроке мы познакомимся с объектом history
, который отвечает за кнопки "Назад" и "Вперёд", расположенные в окне браузера.
Что такое HTML5 History API?
HTML5 History API – это программный интерфейс, посредством которого у нас имеется доступ к истории браузера. В JavaScript он реализован через глобальный объект window.history
.
window.history
// если текущий контекст является window, то обратиться к нему можно просто с помощью history
history
Познакомиться с возможностями этого API чень просто. Для этого достаточно открыть в браузере «Консоль JavaScript» (Ctrl + Shift + J) и ввести команду history
. В прототипе этого объекта мы увидим все методы, которые нам доступны для работы с историей:

Каждая вкладка в браузере имеет свой объект history
. С помощью него мы можем перемещаться по истории, добавлять в неё элементы, реагировать на переходы и делать ещё некоторые вещи.
В браузере история представлена с помощью кнопок «Назад» и «Вперед». С помощью них мы можем перемещаться по истории одного таба.

Таким образом, когда мы, например, переходим по ссылке на какую-то другую страницу, которая открывается в этой же вкладе, то у нас она автоматически добавляется в историю. Теперь в history
будут 2 страницы: текущая и предыдущая. Вернуться на предыдущую страницу можно с помощью кнопки «Назад», а с предыдущей на следующую посредством «Вперед». Если перейти ещё на какую-то страницу, то в истории их уже будет 3.
В JavaScript получить количество элементов в истории можно с помощью свойства length
:
history.length // 3
Перемещаться по истории в JavaScript осуществляется посредством методов back()
и forward()
:
// перейти к предыдущей странице
history.back()
// перейти к следующей странице
history.forward()
Эти методы действуют точно так же, как если бы пользователь нажал соответсвенно на кнопку «Назад» и «Вперед».
JavaScript позволяет так же переместиться сразу на указанное количество шагов по истории. Осуществляется это с помощью метода go()
:
// на 2 страницы назад
history.go(-2)
// на предыдущую
history.go(-1) // аналогично history.back()
// на 2 страницы вперёд
history.go(2)
// на следующую
history.go(1) // аналогично history.forward()
Вызов метода go()
без аргументов или с передачей ему значения (0)
приведёт к обновлению страницы:
history.go()
// или
history.go(0)
Зачем вообще нужен объект history?
С приходом AJAX, мы можем обновлять страницу сайта или веб-приложения на основании данных с сервера без её перезагрузки. Но, как при этом нам отобразить это состояние в URL не перезагружая её?
Например, у нас имеется страница на которой мы сделали постраничную навигацию. При клике на кнопку с номером «2», мы с сервера загрузили новые данные и обновили на основании них часть страницы посредством JavaScript:

Но если поделиться ссылкой на эту страницу или обновить её, то мы не увидим эти изменения. У нас опять будет отображаться страница с номером «1». То есть наш текущий адрес http://127.0.0.1:5500/index.html
не соответствует текущему содержанию страницы. Тут, например, было бы правильно использовать http://127.0.0.1:5500/index.html?p=2
.
В таких сценариях, да и вообще на Ajax-сайтах очень часто используют History API. С помощью него мы можем просто изменить URL-адрес текущей страницы не вызывая при этом её перезагрузку.
Для этого нам в history
доступны 2 метода: pushState()
и replaceState
.
Метод pushState()
добавляет в историю новый переход. Более детально, он делает страницу, которая была текущей до вызова pushState()
, предыдущей. То есть к ней теперь мы можем перейти с помощью кнопки «Назад». А текущей теперь становится та, которую мы добавили в историю с помощью pushState()
. При этом нужно понимать, что посредством pushState()
мы по факту устанавливаем только URL и некоторые записи для неё в истории. Браузер не выполнять переход на этому URL, для обновления контента на странице в этом случае следует использовать JavaScript.
Синтакис:
history.pushState(state, unused)
history.pushState(state, unused, url)
Данный метод имеет 3 параметра:
state
– некоторые данные в формате объекта, которые необходимо связать с создаваемой записью в истории;unused
– не используется и присутствует в методе по историческим причинам, в качестве значения ему можно просто передать пустую строку;url
(необязательно) – URL-адрес новой записи истории (если не указать, то будет использоваться текущий адрес).
Например:
history.pushState({id: 19456622}, '', '/1.html?id=19456622')
// в этом случае в качестве URL будет использоваться текущий адрес документа
history.pushState({id: 19456622}, '')
Получить объект истории можно с помощью свойства state
:
history.state // {id: 19456622}
URL-адрес не обязательно указывать абсолютным. Если задать относительный адрес, то он разрешится относительно текущего URL. Например, если текущий адрес http://127.0.0.1/catalog/
, то после history.pushState({}, '', '19456622')
URL будет http://127.0.0.1/catalog/19456622
.
Новый URL-адрес должен иметь то же origin, что и текущий URL-адрес. Если мы захотим выполнить history.pushState({}, '', 'https://www.google.com/')
для страницы, которое имеет другое происхождение, то будет вызвано исключение:

Метод replaceState()
в отличие от pushState()
просто изменяет текущий элемент истории.
Назначение объекта history
Объект history
отвечает за историю переходов, которые пользователь совершил в переделах одного окна или вкладки браузера. Эти переходы браузер сохраняет в сессию истории текущего окна (вкладки) и пользователь с помощи кнопки "Назад" всегда может вернуться на предыдущие страницы. Кроме кнопки "Назад" пользователю доступна ещё кнопка "Вперёд", которая предназначена для того, чтобы пользователь мог вернуться обратно на страницы, с которых он ушел с помощью кнопки "Назад". Таким образом, объект history
отвечает за 2 эти кнопки, и позволять не только имитировать их нажатие, но добавлять и изменять записи в истории, перехватывать события при нажатии на эти кнопки и др.
Например: В некотором окне (вкладке) браузера пользователь изначально открыл страницу 1. Просмотрев эту страницу, пользователь нажал в ней на некоторую ссылку и перешёл на страницу 2. На второй странице пользователь снова нажал на ссылку и перешёл на страницу 3. В результате сессия истории для этого окна (вкладки) будет состоять из 3 элементов.

На текущий момент для пользователя доступна кнопка "Назад". При нажатии на эту кнопку пользователь может вернуться на страницу 2.

В этот момент времени для пользователя становится доступны кнопки "Назад" и "Вперёд". При нажатии на кнопку "Назад" пользователь может вернуться на страницу 1, а при нажатии на кнопку "Вперёд" - на страницу 3. Таким образом, пользователь с помощью кнопок "Назад" и "Вперёд" может перемещаться по истории внутри этого окна (вкладки).
Каждый элемент в сессии состоит из:
- data - это некоторые данные, которые можно связать с определённым элементом истории. В основном они используются для того чтобы восстановить состояние динамической страницы при переходе к ней с помощью кнопки "Назад" или "Вперёд". Т.е. сначала Вы сохраняете состояние страницы, а точнее динамических её блоков, которые загружаются с помощью технологии AJAX, в
data
. А потом, когда пользователь переходит к ней с помощью кнопки "Назад" или "Вперёд", Вы можете восстановить состояние этой страницы, а точнее этих динамических блоков (т.к. одного URL не достаточно) с помощью информации, сохранённой вdata
. - title - название пункта истории. В настоящее время большинство браузеров не поддерживают возможность установления названия пункта с помощью JavaScript. Браузеры в качестве названия пункта истории используют название страницы, т.е. текст, расположенный между открывающим
<titie>
и закрывающим</title>
тегами HTML страницы. - url - URL адрес страницы.
Свойства, методы и события объекта history
- Свойство history.length - возвращает количество элементов в сессии истории текущего окна (вкладки). Другими словами, данное свойство возвращает количество переходов, которые Вы можете выполнить в пределах текущего окна как вперед, так и назад. Данное свойство доступно только для чтения.
- Свойство history.state - позволяет получить данные (
data
) текущего элемента истории. Эти данные можно добавить к элементу истории с помощью методовhistory.pushState()
иhistory.replaceState()
. - Метод history.go(). Он позволяет переместить пользователя на некоторое количество страниц вперёд или назад по истории. Метод
history.go()
имеет один обязательный параметр - это число, на которое надо переместить пользователя вверх или вниз по истории. Например,history.go(2)
- осуществляет перемещения пользователя на 2 шаг назад, ahistory.go(-2)
на 2 шага вперёд. Если в качестве параметра указать значение 0, то данный метод вызовет перезагрузку страницы. Если указать в качестве значение число, которое превышает количество шагов, которые может совершить пользователь в текущем окне, то ни чего не произойдёт. - Метод history.back() - осуществляет перемещение пользователя на одну страницу назад по истории, т.е. он программно 'имитирует" нажатие кнопки "Назад" в браузере. Также метод
history.back()
можно выполнить с помощью методаhistory.go(-1)
. - Метод history.forward() - осуществляет перемещение пользователя на одну страницу вперёд по истории, т.е. он программно "имитирует" нажатие кнопки "Вперёд" в браузере. Также метод
history.forward()
можно выполнить с помощью методаhistory.go(1)
. - Метод history.pushState() - позволяет добавить новую запись в сессию истории текущего окна (вкладки). Добавление записи (элемента) осуществляется в конец сессии истории.
JavaScript
history.pushState(data,title[,url]);
Данный метод принимает 3 параметра:
data
(обязательный параметр) - некоторые данные, которые будут связаны с этой записью в сессии истории. Если в данных нет необходимости, то используйте в качестве параметра значениеnull
.title
(обязательный параметр) - название записи в сессии истории.url
(необязательный параметр) - это URL записи в сессии истории. Если URL не указать, то будет использоваться текущий адрес страницы.
- Метод history.replaceState() - позволяет изменить текущий элемент истории.
JavaScript
Данный метод принимает 3 параметра. Назначение параметров этого метода аналогично методуhistory.replaceState(data,title[,url]).
history.pushState()
. - Событие popstate. Данное событие вызывает браузер при навигации по истории. Т.е. с помощью его Вы можете обрабатывать события, происходящие в браузере, когда пользователь нажимает на кнопку "Назад" или "Вперёд", или при выполнении методов
history.go()
,history.back()
,history.forward()
.JavaScriptonpopstate = function(event) { //код обработки события popstate //например: console.log(event.state); }
JavaScriptwindow.addEventListener ("popstate", function (e) { //код обработки события popstate });
В качестве примера рассмотрим работу с объектом history
в консоли браузера:
- Откроем вкладку в браузере и введём в адресной строке
http://www.yandex.ru/
и нажмём Enter. - В этой же вкладке в адресной строке введём
http://getbootstrap.com/
и нажмём опять Enter. Если посмотреть на кнопку "Назад", то он стала активной и позволяет перейти на один шаг назад, т.е. на страницуhttps://www.yandex.ru/
. Кроме этого можно увидеть список элементов истории, если нажать правой кнопкой мыши на кнопку "Назад". - Откроем консоль (клавиша F12 в браузере, вкладка "Консоль") и поработаем с историей с помощью JavaScript:
- Узнаем количество элементов в истории:
history.length
; - Добавим новый элемент в историю:
history.pushState(null,null,"http://getbootstrap.com/css/");
- Перезагрузим страницу с помощью объекта
history
:history.go(0);
- Для примера заменим текущий элемент истории и свяжем с ним строку "Привет":
history.replaceState("Привет",null,"http://getbootstrap.com/javascript/");
- Получим данные связанные с этим элементом истории:
history.state;
- Перейдём на 2 шага назад по истории, т.е. на страницу
http://www.yandex.ru/
:history.go(-2);

Комментарии: 11
Спасибо за хороший разбор, понятно и просто объясняете. Только не понял, почему при history.pushState в скрипте первой страницы в браузере меняется адрес на этот новый (хотя содержание страницы остается первой страницы)
Спасибо! Методы
history.pushState
иhistory.replaceState
изменяют URL и другие данные истории, но они не изменяют содержимое страницы и не осуществляют переход по этому URL. Изменять контент в этом случае нужно самостоятельно с помощью JavaScript.По большому счёту эти методы и нужны в основном для AJAX-сайтов, а URL изменяем для того, чтобы при перезагрузке страницы или при переходе по этой ссылке пользователь увидел тот же контент, который видит сейчас.
понял, то есть используются для AJAX-сайтов сайтов, спасибо!
Да, в основном для сайтов, в которых вы обновляете какую-то часть страницы без её перезагрузки и хотите как-то это состояние показать в URL. Например, может использоваться для реализации постраничной навигации по товарам.
В одном месте написано:
«Например, history.go(2) — осуществляет перемещения пользователя на 2 шаг назад, a history.go(-2) на 2 шага вперёд.»
А в другом
«Также метод history.back() можно выполнить с помощью метода history.go(-1)»
«Также метод history.forward() можно выполнить с помощью метода history.go(1)»
И не понятно куда же перемещает значение с минусом — назад или вперед? Пойду выяснять практическим путём.
Остаются html + css, а js нет.
Использовал getScript но к сожалению при нажатии назад уже загружается весь сайт, как исправить?
Как сделать так чтобы при нажатии на кнопку назад страница высодилась моментально со всеми предыдущими ajax запросами
Просто страницы у меня передаются в GET параметрами допустим index.php?id=5, а запросы на сервер POST параметрами.
Если вы используете POST, то тогда вам нужно сохранять настройки страницы в какое-нибудь другое место. Например, в cookies или local storage. А затем использовать их для восстановления вида страницы, которую пользователю она была предоставлена до этого.