Ajax, кнопка возврата и обновления DOM


113

Если javascript изменяет DOM на странице A, пользователь переходит на страницу B, а затем нажимает кнопку «Назад», чтобы вернуться на страницу A. Все изменения DOM страницы A теряются, и пользователю предоставляется версия, которая была первоначально получена с сервера.

Так работает на stackoverflow, reddit и многих других популярных сайтах. (попробуйте добавить тестовый комментарий к этому вопросу, затем перейдите на другую страницу и нажмите кнопку «Назад», чтобы вернуться - ваш комментарий будет «удален»)

Это имеет смысл, однако некоторые веб-сайты (apple.com, basecamphq.com и т. Д.) Каким-то образом заставляют браузер предоставлять пользователю последнее состояние страницы. (перейдите по адресу http://www.apple.com/ca/search/?q=ipod , щелкните ссылку "Скачивания" вверху, а затем нажмите кнопку "Назад" - все обновления DOM будут сохранены)

откуда взялось несоответствие?


Интересно, что Apple запоминает состояние без изменения хеша .. хммм
— Джеймс

Apple выглядит так, будто они просто манипулируют кешированием ответов
— BigBlondeViking

Как уже предполагали другие, это не связано с javascript или ajax. Вы должны удалить эти теги, чтобы получить правильные ответы.
— BYK

Пример Apple плохой. Если вы закроете область поиска [например: продукты], щелкните свою ссылку, а затем нажмите назад, DOM не сохраняется. вы ищете решение для хеширования, которое многие предложили.
— BigBlondeViking

Когда я нажимаю кнопку «Назад», Apple не запоминает, на какой странице результатов поиска я был. Используя IE7. Вам нужно хеш-решение. См .: Facebook.
— Джош Стодола

Ответы:


106

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

Некоторые браузеры хранят текущее состояние всей веб-страницы в так называемом «bfcache» или «кеше страницы». Это позволяет им очень быстро повторно отображать страницу при навигации с помощью кнопок «назад» и «вперед» и сохраняет состояние модели DOM и всех переменных JavaScript. Однако, когда страница содержит события onunload, эти события могут потенциально перевести страницу в нефункциональное состояние, и поэтому страница не сохраняется в bfcache и должна быть перезагружена (но может быть загружена из стандартного кеша) и повторно загружена. рендеринг с нуля, включая запуск всех обработчиков загрузки. При возврате на страницу через bfcache DOM сохраняется в своем предыдущем состоянии, без необходимости запускать обработчики загрузки (потому что страница уже загружена).

Обратите внимание, что поведение bfcache отличается от стандартного кеша браузера в отношении Cache-Control и других заголовков HTTP. Во многих случаях браузеры кэшируют страницу в bfcache, даже если в противном случае он не сохранил бы ее в стандартном кеше.

jQuery автоматически прикрепляет событие выгрузки к окну, поэтому, к сожалению, использование jQuery не позволит вашей странице храниться в bfcache для сохранения DOM и быстрого перехода назад / вперед.. [Обновление: это было исправлено в jQuery 1.4 и теперь применимо только к IE]


3
Вы полностью справились с этим. как reddit, так и stackoverflow используют jquery, а basecamp и apple используют prototypejs. это почти все объясняет.
— lubos hasko

+1 интересно (хотя и не кроссбраузерно) вопрос сильно отличается от того, когда он начался ...
— BigBlondeViking

1
он, вероятно, будет кроссбраузерным, потому что я могу воспроизвести его и в своем Internet Explorer. Я уверен, что каждый веб-браузер с включенным javascript в любом случае сталкивался с этой проблемой. но это действительно беспорядок, когда вы думаете об этом, кнопка возврата всегда должна перенаправлять людей на страницу, которую они видели последней, со всеми обновлениями DOM, состоянием javascript и т. д. разработчики не должны нарушать это, делая что-то в событии выгрузки и если они это сделают, веб-браузеры не должны пытаться решить проблему, вообще не используя bfcache. все событие разгрузки - одна большая шутка. Я уверен, что в 99% случаев он используется для исправления утечек памяти.
— lubos hasko

1
В частности, утечки памяти IE. :) Событие выгрузки jQuery также исправляет (совершенно не связанную) ошибку в Firefox 2. Но это не нужно для других браузеров. dev.jquery.com/ticket/3015 Полагаю, я слышал о других способах использования onunload, таких как отслеживание исходящих кликов или сохранение состояния веб-приложения, но у меня никогда не было причин использовать его самому, и если разработчики хотят сайты медленнее и болезненнее для своих пользователей (я ненавижу, как переход назад к страницам комментариев Reddit сбрасывает состояние свернутого комментария), это их прерогатива.
— Miles

1
Событие выгрузки прикреплено только к IE, а не к firefox и chrome. Последняя версия safari сохраняет состояние dom, при этом разработчик не должен ничего делать.
— Дэвид

15

Я пытался заставить Chrome вести себя так же, как Safari, и единственный способ, который, как я обнаружил, работает, - это установить Cache-control: no-storeв заголовках. Это заставляет браузер повторно загружать страницу с сервера, когда пользователь нажимает кнопку возврата. Не идеально, но лучше, чем показывать устаревшую страницу.


5
Это правильный ответ на исходный вопрос. Если вы хотите принудительно перезагрузить сервер с помощью кнопки возврата, используйте cache-control 'no-store, no-cache, must-revalidate'. Chrome хочет не хранить, а IE требует повторной проверки. Для других браузеров (и w3c) достаточно no-cache.
— woens

3

Facebook запоминает состояние страницы, изменяя хэш-идентификатор в URL-адресе для запросов ajax. Эти изменения записываются в историю браузера, поэтому, когда пользователь нажимает кнопку «Назад», хеш изменяется на то, что было раньше. Таким образом, подразумевается, что вам понадобится некоторый Javascript для отслеживания идентификатора has и реакции на его изменение браузером. У Андреаса Бликста есть скрипт для мониторинга хэшей .


на сегодняшний день он не умирает, так что могу сказать мне, что Facebook делает сейчас
— Равиндер Пайал

3

Это не имеет ничего общего с символом решетки (#).

Если вы проверите HTTP-заголовки Apple, они просто кешируют страницу.


Пример Apple плохой, они не «сохраняют» состояние страницы, его предположение, что DOM сохраняет это неправильно
— BigBlondeViking

2

Использование идентификатора хэша / фрагмента URL-адреса - довольно распространенный способ перехвата / запоминания состояния в веб-приложении, которое полагается на обновления Ajax и DOM.

Проверьте Really Simple History проект для некоторых идей. Можно отслеживать URL-адрес на предмет изменений хэша, и rsh делает это с учетом различий в браузерах.


1

Для всех, кто сталкивается с проблемами, Railsи это - ваша проблема не в bfcache (я так думал) - это turbolinksжемчужина. Вот как это удалить.

Надеюсь, это сэкономит вам время и ударится головой о стену.


0

То, что вы ищете, - это какой-то тип управления хешем URL. # В URL-адресе предназначен только для клиентской стороны.

Когда вы меняете состояние спины с помощью JS, вы обновляете данные в # URL-адреса.

Также вы добавляете какой-то тип опроса, который отслеживает, изменился ли хэш, и загружает состояние страницы на основе новых данных в хеше.

Взгляните на это:

http://ajaxpatterns.org/Unique_URLs


3
это не имеет ничего общего с символом решетки.
— Лука Маттеис,

3
Вы ошибаетесь, он ищет наиболее распространенный способ сохранить состояние страницы в решении AJAX.
— BigBlondeViking
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.