HTML5 History API: "popstate" не вызывается при переходе назад с другой страницы

Мне нужно поддерживать сайт с формой поиска AJAX (например, для книг), и я хочу, чтобы результаты поиска были частью истории браузера.

Поэтому я установил обработчик события "popstate"

window.addEventListener('popstate', function(e) {
    alert("popstate: " + JSON.stringify(e.state));
});

и вызовите pushState() после успешного AJAX-запроса:

var stateObj = { q: "harry potter" };
window.history.pushState(stateObj, "Result", "/search");

Тогда мой поток кликов:

  1. Загрузите страницу с формой поиска - НОРМАЛЬНЫЙ запрос - путь /
  2. Введите строку запроса и отправьте форму - запрос AJAX - изменение пути к /search
  3. Нажмите на результат поиска - НОРМАЛЬНЫЙ запрос - изменение пути к /books/harry-potter

  1. Теперь, когда я возвращаюсь назад, нажимая кнопку "Назад" в браузере, я ожидаю, что событие "popstate" будет запущено с соответствующим объектом состояния. Но ничего не происходит. - путь меняется на /search

  1. Когда я возвращаюсь еще раз, я получаю предупреждение popstate: null - путь меняется на /

  2. И когда я иду вперед после этого, я получаю popstate: {"q":"harry potter"} - путь меняется на /search


Таким образом, важное событие popstate (событие со строкой запроса) запускается только при движении вперед, но не при возврате назад.

Это потому, что я возвращаюсь с сайта, чья запись в истории была создана автоматически, а не программно pushState? Но если так, то API History будет иметь смысл только для полных одностраничных приложений.

Поведение одинаково в любом браузере. Надеюсь, вы можете помочь мне:)

2 ответа

Для любого, кто хочет немного больше объяснить, почему событие popstate происходит только в определенных сценариях, это помогло мне:

На странице события MDN popstate говорится:

Событие popstate отправляется в окно каждый раз, когда активная запись истории изменяется между двумя записями истории для одного и того же документа.

а также

Событие popstate запускается только при выполнении действия браузера, такого как нажатие кнопки "назад" (или вызов history.back() в JavaScript), при переходе между двумя записями истории для одного и того же документа.

Таким образом, похоже, что popstate вызывается только при переходе к различным URL-адресам в одном документе. Это прекрасно работает для SPA, но не для чего-либо еще.

В качестве дополнительного примечания, спецификация html5 для истории сеансов не имеет особой ясности относительно того, когда вызывается событие popstate:

Событие popstate вызывается в определенных случаях при переходе к записи истории сеанса.

Что может указывать на то, что разные браузеры будут относиться к этому по-разному.

Я хотел бы больше понимания от кого-либо еще

Есть по крайней мере один способ заставить это работать, основанный на этом отрывке из Mozilla « Работа с API истории»:

... Когда страница перезагрузится, она получит сообщениеonloadсобытие, но не событие. Однако, если вы прочтетеhistory.stateсвойство, вы вернете объект состояния, который вы получили бы, если быpopstateвыстрелил.

Минимальный рабочий пример можно найти во фрагменте ниже.

Запустите фрагмент кода и выполните следующие действия, чтобы увидеть его в действии:

  1. нажмите «Заполнить», чтобы динамически добавить текст на дисплей (по сути, это имитация AJAX)
  2. нажмите «прочь», чтобы перейти на сайт example.org (не волнуйтесь, это происходит внутриiframe)
  3. нажмите кнопку «Назад» в браузере: дисплей вернется в заполненное состояние.
  4. нажмите браузер «назад» еще раз, чтобы очистить дисплей (исходное пустое состояние)

Как отмечено здесь:

The stateобъект может быть чем угодно, что можно сериализовать.

Другие вопросы по тегам