Исправляем проблему с history.replaceState() в Chrome
Быстрый ответ
Для модификации URL-адреса в браузере и соответствующего состояния без необходимости перезагружать страницу и создавать новую запись в истории браузера, воспользуйтесь методом history.replaceState()
. Этот метод отлично подходит для AJAX-навигации в single-page приложениях.
Логика работы:
// URL изменяется на "updated-page.html", но страница при этом не перезагружается
history.replaceState({ detail: 'update' }, '', 'updated-page.html');
Суть: URL-адрес обновляется до updated-page.html
, весь контент страницы остаётся без изменений. Объект состояния ({ detail: 'update' }
) используется для отслеживания изменений в рамках текущей веб-страницы.
Важно помнить, что history.replaceState()
не влияет на заголовок документа. Для его изменения необходимо отдельно прописать значение document.title
:
Пример обновления заголовка:
// Теперь переименуем заголовок
document.title = 'Обновленный заголовок страницы';
history.replaceState({ detail: 'update' }, 'Обновленный заголовок страницы', 'updated-page.html');
Навигация по браузерному ландшафту
Каждый браузер имеет свои специфические характеристики, и они не всегда корректно обрабатывают параметр title
для replaceState()
и pushState()
. В лучшем понимании этих тонкостей понадобится кое-какое время.
Выживание среди браузерных различий
Протестируйте свой код во всех популярных браузерах до релиза проекта, чтобы предотвратить неприятные сюрпризы. Имейте в виду, что поведение replaceState()
может различаться в разных браузерах, например, Chrome или Opera.
Изменение заголовка документа
Когда осуществляется изменение заголовка документа, делаем это таким образом:
// Тсс, нас тут нет
document.getElementsByTagName('title')[0].innerHTML = 'новый заголовок';
Отслеживание изменений в навигации
Используйте событие window.onpopstate
, чтобы отследить изменения в навигации истории браузера:
// О, кто-то нажал кнопку "назад"?
window.onpopstate = function(event) {
if (event.state) {
updateContent(event.state.detail);
}
};
function updateContent(detail) {
// Здесь размещаем логику для обновления контента
}
Обход препятствий AJAX
replaceState()
в сочетании с AJAX позволяет получать и показывать новый контент, не вовлекая пользователя в ожидание перезагрузки страницы.
// Это время удивить пользователя новым контентом
function loadContent(url) {
// Получаем контент, а затем обновляем URL без перезагрузки страницы
fetch(url)
.then(response => response.text())
.then(html => {
document.getElementById('content').innerHTML = html;
history.replaceState({ content: html }, '', url);
});
}
Если вы используете jQuery, это облегчает управление AJAX-контентом и взаимодействие с pushState
и popstate
.
Визуализация
Представьте history.replaceState()
как хитроумного ассистента 🕵️♂️, который сценарий книги меняет так, не вызывая подозрений:
До использования ReplaceState: 📖 [Страница 1 – Вступление, Страница 2 – Развитие сюжета, Страница 3 – Кульминация]
Возвращается наш смекалистый помощник:
history.replaceState({page: 2}, "Заголовок", "/page-2");
После применения ReplaceState: 📖 [Страница 1 – Вступление, Страница 2 – Впечатляющий поворот сюжета!, Страница 3 – Кульминация]
Прочие даже не заподозрят, что что-то изменилось, история продолжает течь своим чередом.
Полезные материалы
- Метод History: replaceState() – Web API | MDN — подробное описание метода
replaceState()
. - Использование HTML5 History API | CSS-Tricks — руководство по работе с HTML5 History API.
- GitHub – devote/HTML5-History-API — повышение совместимости History API в браузерах, которые его не поддерживают изначально.
- javascript – Как изменить URL без перезагрузки страницы? – Stack Overflow — обсуждения на Stack Overflow по вопросу изменения URL без перезагрузки страницы.
- Якоря заголовков Markdown на GitHub · GitHub — использование
history.replaceState()
на практике.