Сохранение истории изменений хэша/привязки в JavaScript

В настоящее время я реализую библиотеку JavaScript, которая отслеживает историю изменений хеш-части в адресной строке. Идея состоит в том, что вы можете сохранить состояние в хэш-части, а затем использовать кнопку «Назад», чтобы вернуться к предыдущему состоянию.

В большинстве последних браузеров это происходит автоматически, и вам нужно только опросить свойство location.hash на наличие изменений (в IE8 вам даже не нужно этого делать; вы просто прикрепляете функцию к событию onhashchange).

Мне интересно, какие существуют методы отслеживания истории? Я реализовал функции, которые были протестированы для работы в Internet Explorer 6/7/8, Firefox и Chrome, но как насчет других браузеров? Вот способы, которыми я сейчас храню историю:

Изменить: вместо этого см. мой ответ ниже для пошагового обзора различных браузеров.


person Blixt    schedule 03.07.2009    source источник


Ответы (5)


Прежде всего, спасибо вам, ребята, что ответили! знак равно

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

Прежде всего, моя готовая Hash библиотека. Это автономная библиотека без зависимостей. Он имеет две функции: Hash.init(callback, iframe) и Hash.go(newHash). Функция обратного вызова вызывается всякий раз, когда хэш изменяется с новым хэшем в качестве первого аргумента, а в качестве второго аргумента — флагом, указывающим, вызывается ли обратный вызов из-за начального состояния (true) или фактического изменения хэша (false).

Hash.js (лицензия MIT)

Я также сделал плагин jQuery для упрощения использования. Также добавляет глобальное событие hashchange. См. пример в исходном коде, как его использовать.

jquery.hash.js (лицензия MIT)

Чтобы увидеть их в использовании, перейдите на мою страницу «области» JavaScript:

Сфера JavaScript от Blixt

Интернет Эксплорер 8

Плавный круиз! Просто примените одно из них onhashchange к объекту window (используя attachEvent) и получите значение location.hash в обработчике событий.

Не имеет значения, щелкает ли пользователь ссылку с хэшем или вы устанавливаете хэш программно; история сохраняется отлично.

Хром, Фаерфокс, Сафари 3+, Опера 8+

Плавный круиз! Просто опросите об изменениях свойства location.hash, используя setInterval и функцию.

История работает идеально. Для Opera я установил history.navigationMode на 'compatible'. Честно говоря, я не уверен, что он делает, я сделал это по рекомендации из комментария в коде YUI.

Примечание. Opera нуждается в дополнительном тестировании, но у меня пока все работает нормально.

Причудливый бонус-сюрприз! (Может быть?!) Оказывается, Firefox (подтверждено только в 3.5+) декодирует свойство location.hash, поэтому это может вызвать событие hashchange дважды (сначала для закодированной версии, а затем для незакодированной версии). — это новая версия моей библиотеки Hash.js, которая учитывает это, используя вместо этого свойство location.href (изменения предоставлены Аароном Оглом).

Интернет Эксплорер 6, 7

Теперь становится противнее. История переходов в старых версиях Internet Explorer игнорирует изменения хэша. Чтобы обойти это, общепринятым решением является создание iframe и установка его содержимого в новый хэш. Это создает новую запись в истории навигации. Когда пользователь возвращается, это изменяет содержимое iframe на его предыдущее содержимое. Обнаружив изменение содержимого, вы можете получить его и установить в качестве активного хэша.

Проверка изменений свойства location.hash по-прежнему необходима для ручного изменения текущего адреса. Однако остерегайтесь причуд, о которых я упоминал ниже.

Хотя это решение кажется лучшим, оно все еще не идеально в Internet Explorer 6, что немного странно в отношении кнопок «назад/вперед». Однако Internet Explorer 7 работает нормально.

Неожиданный причудливый бонус №1! В Internet Explorer 6 всякий раз, когда в хэше есть вопросительный знак, он извлекается и помещается в свойство location.search ! Он удален из location.hash свойства. Однако, если существует реальная строка запроса, location.search вместо этого будет содержаться именно она, и вы сможете получить полный истинный хеш, только проанализировав свойство location.href .

Неожиданный причудливый бонус №2! Если установлено свойство location.search , любые последующие # персонажи будут удалены из location.href location.hash) свойство. В Internet Explorer 6 это означает, что всякий раз, когда в пути или хэше есть вопросительный знак, вы столкнетесь с этой особенностью. В Internet Explorer 7 эта особенность возникает только при наличии знака вопроса в пути. Вам нравится единообразие Internet Explorer?

Неожиданный причудливый бонус №3! Если другой элемент на странице имеет тот же идентификатор, что и значение хеша, этот хэш полностью испортит историю. Таким образом, эмпирическое правило заключается в том, чтобы избегать хэшей с тем же идентификатором, что и любые элементы на странице. Если хэши генерируются динамически и могут конфликтовать с идентификаторами, рассмотрите возможность использования префикса/суффикса.

Другие браузеры

Если у вас нет необычной пользовательской базы, вам не нужно будет поддерживать больше браузеров. Браузеры, не перечисленные выше, относятся к категории использования ‹1%.

person Blixt    schedule 07.07.2009
comment
Это автономная библиотека без зависимостей. - Спасибо! Отлично. - person outcassed; 26.08.2009
comment
Очевидный недостаток этого: hashchange срабатывает, когда вы нажимаете на новую ссылку, если ссылка была создана с вашим программным обеспечением (я считаю, что простого «a» недостаточно, ваш код должен вмешиваться в него), или если вы посещаете с другой страницы. Он не срабатывает в браузере вперед и назад. Для этого, я думаю, вам нужен таймер для опроса изменений, судя по другим реализациям. - person ijw; 04.10.2009
comment
Я знаю, что это немного устарело, но может ли кто-нибудь подробнее рассказать о бонусе-сюрпризе № 3? В чем именно проблема? У вас есть тестовый пример, демонстрирующий проблему? - person Grodriguez; 16.08.2013

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

Они хорошо описывают свою реализацию, и я нахожу их исходный код очень читабельным.

Вот что написано об Opera

* location.hash is a bit buggy on Opera. I have seen instances where
* navigating the history using the back/forward buttons, and hence
* changing the URL, would not change location.hash. That's ok, the
* implementation of an equivalent is trivial ... more below

При поиске источника я также нашел некоторые приспособления для Safari 1.x и 2.0. Похоже, вам это будет интересно.

Надеюсь, это поможет.

person Keith Bentrup    schedule 04.07.2009
comment
Да, несколько фрагментов моего кода вдохновлены их реализацией. Я видел их реализацию Safari, но я не смог найти простой способ заставить его работать, и мне пришлось бы значительно увеличить размер моего кода, поэтому мне интересно, используется ли Safari 2 и ниже. достаточно людей, чтобы гарантировать поддержку. - person Blixt; 04.07.2009
comment
Safari 2 составлял 0,5% в январе 2009 г. согласно: /globalstats.php?date=2009-01-31. Таким образом, 1 из 200 по состоянию на 6 месяцев назад. - person Keith Bentrup; 05.07.2009
comment
Спасибо Кит! Тогда я решу не поддерживать Safari 2, потому что код мешает работе современных браузеров, если только не реализован анализ браузера... и это мне не нравится. знак равно - person Blixt; 06.07.2009

Я не уверен, что полностью понимаю ваши потребности, но я использовал библиотеку Really Simple History (http://code.google.com/p/reallysimplehistory/) для реализации чего-то подобного. Вы можете увидеть это здесь: http://whiteoak.sourceforge.net/

person Itay Maman    schedule 03.07.2009
comment
Мне нужен легкий способ просто отслеживать хеш-значение и поддерживать кнопки «назад/вперед» с одинаковым поведением во всех широко используемых браузерах. RSH не кажется такой библиотекой, так как она занимает более 9 КБ при сжатии YUI и все еще зависит от внешних библиотек... Моя собственная библиотека в настоящее время весит 835 байт в сжатом виде и работает в IE6+, Firefox, Chrome и, предположительно, в Opera. 8+ и Safari 3+ без зависимостей... Мне в основном интересно, не хватает ли мне каких-либо браузеров и как их поддерживать. - person Blixt; 03.07.2009

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

В IE (проверено только в IE7) история с хешем работает корректно при наличии на экране элемента страницы с id, равным хешу. Например, подумайте об оглавлении (TOC) на вики-странице. Каждая ссылка в TOC ссылается на хэш элемента имени id или привязки где-то на странице:

<div id="TOC">
<a id="SampleHeaderLink" href="#SampleHeader">Sample Header</a>
</div>

<h2 id="SampleHeader">Sample Header</a>

Таким образом, при нажатии SampleHeaderLink настройка браузера IE по умолчанию — перейти к SampleHeader и зарегистрировать состояние в истории. Использование кнопки «Назад» и «Вперед» работает должным образом.

Однако, если элемент div SampleHeader не существует на странице, браузер только регистрирует изменение URL-адреса, но не создает для него новое состояние.

Опять же, это проверено только в IE7. И я не знаю, насколько общеизвестна эта информация, но я так и не нашел ничего связанного, когда просматривал, чтобы исправить эту проблему в своем собственном приложении.

person Beez    schedule 28.02.2011
comment
Я упоминаю об этом, вернее, об обратной стороне. При использовании подхода iframe история будет полностью испорчена, если вы попытаетесь использовать идентификатор существующего элемента в качестве хэша. Так что я думаю, вам нужно либо вообще не использовать идентификаторы, либо просто использовать идентификаторы. - person Blixt; 01.03.2011

GWT обеспечивает управление историей. Это также неотъемлемая часть их концепции MVP. Они также расширили API истории с местами и действиями.

person James Annesley    schedule 08.08.2011