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в заголовках. Это заставляет браузер повторно загружать страницу с сервера, когда пользователь нажимает кнопку возврата. Не идеально, но лучше, чем показывать устаревшую страницу.

nornagon
источник
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