Итак, теперь, когда HTML5 вводит history.pushState
изменения в истории браузеров, веб-сайты начинают использовать это в сочетании с Ajax вместо изменения идентификатора фрагмента URL.
К сожалению, это означает, что эти звонки больше не могут быть обнаружены onhashchange
.
Мой вопрос: есть ли надежный способ (взлом?;)), Чтобы определить, когда сайт использует history.pushState
? В спецификации ничего не говорится о возникающих событиях (по крайней мере, я ничего не смог найти).
Я попытался создать фасад и заменил его window.history
своим собственным объектом JavaScript, но это никак не повлияло.
Дальнейшее объяснение: я разрабатываю дополнение для Firefox, которое должно обнаруживать эти изменения и действовать соответственно.
Я знаю, что несколько дней назад был похожий вопрос, который спрашивал, будет ли эффективно прослушивание некоторых событий DOM , но я бы не стал полагаться на это, потому что эти события могут быть сгенерированы по многим различным причинам.
Обновить:
Вот jsfiddle (используйте Firefox 4 или Chrome 8), который показывает, что onpopstate
он не срабатывает при pushState
вызове (или я делаю что-то не так? Не стесняйтесь его улучшать!).
Обновление 2:
Другая (побочная) проблема заключается в том, что window.location
не обновляется при использовании pushState
(но я читал об этом уже здесь, на SO, я думаю).
источник
history
объект. Это может быть ненужным в этом случае.window.history
чтения, но свойства объекта истории нет ... Спасибо большое за это решение :)pushState
метод для последующего использования. Поэтому вместо глобальной переменной я решил инкапсулировать весь код во IIFE: en.wikipedia.org/wiki/Immediately-invoked_function_expressionЯ использовал это:
Это почти так же, как галамбалазы .
Это обычно излишне, хотя. И это может не работать во всех браузерах. (Я забочусь только о моей версии моего браузера.)
(И это оставляет переменную
_wr
, так что вы можете захотеть обернуть ее или что-то. Мне было все равно.)источник
Наконец-то нашел «правильный» способ сделать это! Требуется добавить привилегию к вашему расширению и использовать фоновую страницу (не только скрипт контента), но это работает.
Событие, которое вы хотите - это событие
browser.webNavigation.onHistoryStateUpdated
, которое запускается, когда страница используетhistory
API для изменения URL. Он срабатывает только для сайтов, к которым у вас есть разрешение, и вы также можете использовать URL-фильтр для дальнейшего сокращения спама, если вам это нужно. ТребуетсяwebNavigation
разрешение (и, конечно, разрешение хоста для соответствующего домена (доменов)).Обратный вызов события получает идентификатор вкладки, URL, по которому осуществляется переход, и другие подобные подробности. Если вам нужно выполнить действие в сценарии содержимого на этой странице при возникновении события, либо вставьте соответствующий сценарий непосредственно с фоновой страницы, либо попросите сценарий содержимого открыть
port
на фоновой странице при загрузке, сохраните фоновую страницу. этот порт в коллекции индексируется по идентификатору вкладки и отправляет сообщение через соответствующий порт (от фонового сценария к сценарию содержимого) при возникновении события.источник
Вы могли бы привязать к
window.onpopstate
событию?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
Из документов:
источник
history.go
,.back
) функций называются. Но не вклpushState
. Вот моя попытка проверить это, может быть, я что-то не так делаю : jsfiddle.net/fkling/vV9vd Кажется, что это связано только с тем, что если история была измененаpushState
, соответствующий объект состояния передается в обработчик событий, когда другие методы называются.Поскольку вы спрашиваете об аддоне Firefox, вот код, который я получил для работы. Использование не
unsafeWindow
является больше не рекомендуется , и ошибки вне когда PushState вызывается из клиентского сценария после того , изменения:Вместо этого есть API с именем exportFunction который позволяет вводить функцию
window.history
следующим образом:источник
unsafeWindow.history,
наwindow.history
. Это не работает для меня с unsafeWindow.ответ галамбалаза и обезьяна исправляет
window.history.pushState
иwindow.history.replaceState
, но по какой-то причине он перестал работать на меня. Вот альтернатива, которая не так хороша, потому что она использует опрос:источник
Я думаю, что эта тема нуждается в более современном решении.
Я уверен, что
nsIWebProgressListener
был рядом тогда, я удивлен, что никто не упомянул этоИз фреймскрипта (для совместимости с e10s):
Затем слушаю в
onLoacationChange
Это, очевидно, поймает все pushState's. Но есть комментарий, предупреждающий, что он «ТАКЖЕ запускает pushState». Поэтому нам нужно сделать еще несколько фильтров, чтобы убедиться, что это просто pushstate.
Основано на: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
И: resource: //gre/modules/WebNavigationContent.js
источник
Ну, я вижу много примеров замены
pushState
свойства,history
но я не уверен, что это хорошая идея, я бы предпочел создать сервисное событие, основанное на API, похожем на историю, чтобы вы могли контролировать не только состояние push, но и состояние замены а также он открывает двери для многих других реализаций, не опирающихся на API глобальной истории. Пожалуйста, проверьте следующий пример:Если вам нужно
EventEmitter
определение, приведенный выше код основан на источнике событий NodeJS: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js .utils.inherits
реализацию можно найти здесь: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970источник
Я бы предпочел не переписывать собственный метод истории, поэтому эта простая реализация создает мою собственную функцию под названием eventedPush state, которая просто отправляет событие и возвращает history.pushState (). В любом случае, все работает хорошо, но я считаю, что эта реализация немного чище, поскольку нативные методы будут продолжать работать так, как ожидают будущие разработчики.
источник
Основываясь на решении, предоставленном @gblazex , если вы хотите следовать тому же подходу, но с использованием функций стрелок, следуйте приведенному ниже примеру в вашей логике javascript:
Затем реализуйте другую функцию,
_notifyUrl(url)
которая запускает любое необходимое действие, которое может вам понадобиться при обновлении URL текущей страницы (даже если страница вообще не была загружена)источник
Так как я просто хотел новый URL, я адаптировал коды @gblazex и @Alberto S., чтобы получить это:
источник
Я не думаю, что это хорошая идея - модифицировать нативные функции, даже если вы можете, и вы всегда должны сохранять область своего приложения, поэтому хороший подход - не использовать глобальную функцию pushState, вместо этого используйте одну из ваших собственных:
Обратите внимание, что если любой другой код использует встроенную функцию pushState, вы не получите триггер события (но если это произойдет, вам следует проверить свой код)
источник
Стандартно говорится:
нам нужно вызвать history.back () для запуска WindowEventHandlers.onpopstate
Итак, о
делать:
источник