Я использую History API для своего веб-приложения, и у меня есть одна проблема. Я выполняю вызовы Ajax для обновления некоторых результатов на странице и использую history.pushState () , чтобы обновить адресную строку браузера без перезагрузки страницы. Затем, конечно, я использую window.popstate , чтобы восстановить предыдущее состояние при нажатии кнопки возврата.
Проблема хорошо известна - Chrome и Firefox по-разному обрабатывают это событие popstate. Хотя Firefox не запускает его при первой загрузке, Chrome запускает. Я хотел бы иметь стиль Firefox и не запускать событие при загрузке, поскольку он просто обновляет результаты точно такими же при загрузке. Есть ли обходной путь, кроме использования History.js ? Причина, по которой я не хочу его использовать, заключается в том, что ему нужно слишком много JS-библиотек, и, поскольку мне нужно, чтобы он был реализован в CMS с уже слишком большим JS, я хотел бы минимизировать JS, который я помещаю в него .
Итак, хотелось бы знать, есть ли способ заставить Chrome не запускать popstate при загрузке или, может быть, кто-то пытался использовать History.js, поскольку все библиотеки собраны вместе в один файл.
источник
Ответы:
В Google Chrome версии 19 перестало работать решение от @spliter. Как отметил @johnnymire, history.state в Chrome 19 существует, но он равен нулю.
Мое решение - добавить window.history.state! == null для проверки наличия состояния в window.history:
Я тестировал его во всех основных браузерах и в версиях Chrome 19 и 18. Похоже, он работает.
источник
in
иnull
проверить, так!= null
как это тоже позаботитсяundefined
.null
в своихhistory.pushState()
методах, напримерhistory.pushState(null,null,'http//example.com/)
. Конечно, это, вероятно, большинство случаев использования (именно так он настроен в jquery.pjax.js и большинстве других демонстраций). Но если браузеры реализуютwindow.history.state
(например, FF и Chrome 19+), window.history.state может быть ненулевым при обновлении или после перезапуска браузераЕсли вы не хотите принимать особые меры для каждого обработчика, добавляемого в onpopstate, мое решение может быть вам интересно. Большой плюс этого решения также в том, что события onpopstate могут обрабатываться до завершения загрузки страницы.
Просто запустите этот код один раз, прежде чем добавлять какие-либо обработчики onpopstate, и все должно работать должным образом (например, как в Mozilla ^^) .
Как это устроено:
Chrome, Safari и, возможно, другие браузеры webkit запускают событие onpopstate после загрузки документа. Это не предназначено, поэтому мы блокируем события popstate до первого цикла цикла событий после загрузки документа. Это делается с помощью вызовов preventDefault и stopImmediatePropagation (в отличие от stopPropagation stopImmediatePropagation мгновенно останавливает все вызовы обработчика событий).Однако, поскольку состояние готовности документа уже находится в состоянии «завершено», когда Chrome ошибочно запускает onpopstate, мы разрешаем события opopstate, которые запускаются до завершения загрузки документа, чтобы разрешить вызовы onpopstate до того, как документ будет загружен.
Обновление 2014-04-23: исправлена ошибка, из-за которой события popstate блокировались, если сценарий выполнялся после загрузки страницы.
источник
window.history.state
не выполняется при перезагрузке, если состояние было установлено. Установка переменной перед кодом pushState мешает. Ваше решение элегантно и может быть добавлено поверх других скриптов, не затрагивая остальную часть кода. Спасибо.Использование только setTimeout не является правильным решением, потому что вы не знаете, сколько времени потребуется для загрузки содержимого, поэтому возможно, что событие popstate будет сгенерировано после тайм-аута.
Вот мое решение: https://gist.github.com/3551566
источник
Решение было найдено в jquery.pjax.js линий 195-225:
источник
Более прямое решение, чем повторная реализация pjax, - установить переменную в pushState и проверить переменную в popState, чтобы исходное popState не срабатывало непоследовательно при загрузке (не решение для jquery, просто используя его для событий):
источник
window.history.ready
всегда правда.!window.history.ready && !ev.originalEvent.state
- эти две вещи никогда не определяются, когда я обновляю страницу. поэтому код не выполняется.Начальному событию onpopstate Webkit не назначено состояние, поэтому вы можете использовать его для проверки нежелательного поведения:
Комплексное решение, позволяющее вернуться к исходной странице, будет основываться на этой идее:
Хотя это все еще может сработать дважды (с некоторой изящной навигацией), с этим можно справиться, просто проверив предыдущий href.
источник
window.history.state
в iOS оно также равно null. Достаточно просто проверить, имеет ли свойство e.state значение null.Это мой обходной путь.
источник
Вот мое решение:
источник
Лучший способ заставить Chrome не запускать popstate при загрузке страницы - проголосовать за https://code.google.com/p/chromium/issues/detail?id=63040 . Они знают, что Chrome не соответствует спецификации HTML5 уже два полных года, и до сих пор не исправили это!
источник
В случае использования
event.state !== null
возврат в историю к первой загруженной странице не будет работать в немобильных браузерах. Я использую sessionStorage, чтобы отмечать, когда действительно запускается ajax-навигация.источник
В представленных решениях есть проблема с перезагрузкой страницы. Похоже, что следующее работает лучше, но я тестировал только Firefox и Chrome. Он использует действительность, которая кажется разницей между
e.event.state
иwindow.history.state
.источник
e.event
is undefinedЯ знаю, что вы возражали, но вам действительно стоит просто использовать History.js, так как он устраняет миллион несовместимостей браузеров. Я пошел путем ручного исправления, но позже обнаружил, что проблем все больше и больше, о которых вы узнаете только в будущем. Сейчас это действительно не так сложно:
И прочтите api на https://github.com/browserstate/history.js
источник
Это решило проблему для меня. Все, что я сделал, это установил функцию тайм-аута, которая задерживает выполнение функции достаточно долго, чтобы пропустить событие popstate, которое запускается при загрузке страницы.
источник
Вы можете создать событие и запустить его после своего обработчика загрузки.
Обратите внимание: это немного не работает в Chrome / Safari, но я отправил патч в WebKit, и он должен быть скоро доступен, но это «самый правильный» способ.
источник
Это сработало для меня в Firefox и Chrome
источник