Chrome popstate не срабатывает на кнопке «Назад», если пользователь не взаимодействует

Я пытаюсь использовать событие «pushState» и «popstate» для перехвата навигации по кнопке «Назад», однако, хотя событие popstate правильно запускается в Firefox, оно не запускается в Chrome (версия 76.0.3809.87 (официальная сборка) (64). -bit)) если нет взаимодействия с пользователем.

Судя по тестированию, событие popstate срабатывает только в том случае, если пользователь взаимодействует со страницей (т. е. щелкает где-нибудь в документе). Поэтому, если вы загрузите страницу, не взаимодействуя с ней, и нажмете «Назад», функция popstate не будет вызвана.

Я добавил Fiddle, чтобы продемонстрировать это: https://jsfiddle.net/0xwvLndu/

Чтобы протестировать Fiddle в Chrome, просто щелкните ссылку и нажмите кнопку «Назад». Вы не увидите оповещения. Затем снова щелкните ссылку, но на этот раз щелкните в любом месте документа Fiddle, а затем нажмите кнопку «Назад», после чего сработает предупреждение.

Я нашел обсуждение на форуме Chromium, которое может иметь отношение к этой причуде, и, возможно, это было реализовано для предотвращения злоупотребления записями истории - https://groups.google.com/a/chromium.org/forum./#!topic/blink-dev/OCS7g72HtyI и < a href="https://github.com/WICG/interventions/issues/21#issuecomment-425609246" rel="noreferrer">https://github.com/WICG/interventions/issues/21#issuecomment-425609246< /а>

Если это так, значит ли это, что на popstate больше нельзя полагаться для перехвата действий кнопки «Назад», и если да, то есть ли обходное решение?

Ниже приведен пример того, что я тестировал:

window.addEventListener('load', function() {
    history.pushState(null, null, document.URL);
});

window.addEventListener('popstate', function(event) {
    alert('test');
});

Я ожидал, что предупреждение будет вызываться кнопкой «Назад» независимо от взаимодействия с пользователем, но в Chrome этого не происходит.


person Praemon    schedule 03.08.2019    source источник
comment
Совсем недавно я занимался обработкой popstate для восстановления позиций прокрутки, так что это довольно свежо в моей памяти, но я до сих пор не понимаю этот вопрос. Возможно, если бы у вас была пошаговая инструкция (или схема), вы бы получили больше отзывов.   -  person Drenai    schedule 04.08.2019
comment
@Drenai Спасибо за отзыв. Я отредактировал свой вопрос, чтобы попытаться сделать его более конкретным для рассматриваемой проблемы. Надеюсь, это прояснит ситуацию.   -  person Praemon    schedule 04.08.2019
comment
Подробнее об этом я читал по ссылке ниже. Похоже, что Chrome намеренно предотвращает захват поведения кнопки «Назад» по умолчанию (и на то есть веская причина). Если вы найдете способ обойти это, я сомневаюсь, что он будет надежным, поскольку будущие версии Chrome, скорее всего, снова исправят его nakedsecurity.sophos.com/2019/05/09/   -  person Drenai    schedule 04.08.2019
comment
@Drenai Спасибо за статью - помогает подтвердить изменение. Я вижу причину этого, хотя это означает, что законные варианты использования больше не работают. Я предполагаю, что мне нужно будет рассмотреть другие способы достижения того, что мне нужно (но, вероятно, за счет пользовательского опыта).   -  person Praemon    schedule 05.08.2019
comment
Я так рад, что наткнулся на этот вопрос. На всю жизнь я не мог понять, что я делаю неправильно, чтобы страница перезагружалась, когда я нажимаю «Назад». Конечно же, как только я щелкнул несколько мест на своей странице, прежде чем нажать «Назад», все заработало, как и ожидалось. Как странно.   -  person Alex Peters    schedule 05.09.2020


Ответы (2)


Попробуйте добавить setTimeout 0

window.onpopstate = () => setTimeout(alert("Pop"), 0);

При написании функций, обрабатывающих событие popstate, важно учитывать, что такие свойства, как window.location, уже будут отражать изменение состояния (если оно повлияло на текущий URL), а document может по-прежнему не отражать. Если цель состоит в том, чтобы поймать момент, когда новое состояние документа уже полностью на месте, следует использовать вызов метода setTimeout() с нулевой задержкой, чтобы эффективно поместить его внутреннюю функцию обратного вызова, которая выполняет обработку в конце цикла событий браузера. : window.onpopstate = () => setTimeout(doSomeThing, 0);

Контент взят с сайта https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event

В примечании рекомендуется не использовать это, так как браузеры могут удалить это в любое время.

person Jerin Joseph    schedule 20.01.2021

Как предположили другие в комментариях, это должно быть предназначено для программного обеспечения браузера, чтобы предотвратить перехват его поведения кнопки «Назад» по умолчанию.

person IT goldman    schedule 28.12.2020