Изменить URL адресной строки в приложении AJAX для соответствия текущему состоянию

166

Я пишу AJAX-приложение, но когда пользователь перемещается по приложению, мне бы хотелось обновить URL-адрес в адресной строке, несмотря на отсутствие перезагрузки страницы. По сути, я бы хотел, чтобы они могли делать закладки в любой точке и, таким образом, возвращаться к текущему состоянию.

Как люди справляются с поддержанием RESTfulness в приложениях AJAX?

jasonjwwilliams
источник
2
Он используется для отображения состояния ваших приложений, но не имеет ничего общего с «RESTfulness».
Мохамед
29
window.history.pushState(null,'hi','page1?id=32')
Ому
3
принятый ответ был написан 5 лет назад, и тем временем мы получили window.history.pushState, как и сказал @Omu. location.hash принес много проблем и лучше всего избегать этого.
pcarvalho
Я отредактировал ответ, чтобы сделать подход pushState заметным.
jasonjwwilliams

Ответы:

116

Способ сделать это - манипулировать, location.hashкогда обновления AJAX приводят к изменению состояния, для которого вы хотите иметь отдельный URL-адрес. Например, если URL вашей страницы:

http://example.com/

Если функция на стороне клиента выполнила этот код:

// AJAX code to display the "foo" state goes here.

location.hash = 'foo';

Затем URL-адрес, отображаемый в браузере, будет обновлен до:

http://example.com/#foo

Это позволяет пользователям отмечать состояние страницы «foo» и использовать историю браузера для навигации между состояниями.

С этим механизмом вам потребуется разобрать хеш-часть URL на стороне клиента, используя JavaScript для создания и отображения соответствующего начального состояния, так как идентификаторы фрагмента (часть после #) не отправляются в сервер.

Плагин hashchange Бена Алмана делает последний легким, если вы используете jQuery.

Дейв Уорд
источник
Похоже, ты прав. Это единственный подход. Это похоже на хорошее подробное объяснение вашего совета: < ajaxpatterns.org/Unique_URLs >
jasonjwwilliams
@buymeasoda Спасибо за редактирование; Я не уверен, о чем я думал, когда писал эту часть.
Дейв Уорд
1
Вау, этот ответ был очень полезным. Хотя примеры URL немного сбивают с толку, SO может автоматически заменять ссылки заголовками. Как насчет замены их чем-то вроде example.com и example.com/#foo, чтобы мы могли видеть весь URL в открытом тексте.
Нил
4
@Pascal Вы можете, но только в браузерах, которые поддерживают pushState в HTML5. Хорошая информация об этом здесь: diveintohtml5.info/history.html
Дейв Уорд
1
В итоге я стал большим поклонником history.js, чтобы охватить основы совместимости браузеров github.com/andreasbernhard/history.js
jocull
18

Посмотрите на такие сайты, как book.cakephp.org. Этот сайт меняет URL без использования хеша и использует AJAX. Я не уверен, как это происходит, но я пытался понять это. Если кто-нибудь знает, дайте мне знать.

Также github.com при просмотре навигации в определенном проекте.

daniel.wright
источник
Я заметил это с GitHub неделю или около того назад. Как же они это делают? Должен вернуться и проверить.
Дрю Ноакс
16
Кажется, они используют функцию JavaScript pushState (). Это добавляет к истории вашего браузера. Посмотри на это; это довольно интересно и круто.
daniel.wright
Спасибо за это, это было именно то, что я искал. Я задавался вопросом, как Github сделал это. Сначала я думал, что это должно быть перезагрузка, но были только запросы AJAX. В Opera это действительно перезагрузило страницу.
kamranicus
Подобная техника используется fb при навигации по страницам разных групп. У вас есть левый столбец навигации, в котором упоминаются разные группы. Когда вы нажимаете на определенное имя группы, URL-адрес изменяется, и вместе с URL-адресом изменяется только содержимое главной панели содержимого (без хэша). Поэтому, когда пользователь перезагружает страницу, он не перенаправляется на домашнюю страницу, а на страницу групп.
Madeyedexter
17

Вряд ли писатель захочет перезагрузить или перенаправить своего посетителя при использовании Ajax. Но почему бы не использовать HTML5 pushState/ replaceState?

Вы сможете изменять адресную строку столько раз, сколько захотите. Получите естественный вид URL с AJAX.

Проверьте код на моем последнем проекте: http://iesus.se/

Iesus
источник
11

Это похоже на то, что сказал Кевин. У вас может быть состояние клиента как некоторый объект javascript, и когда вы хотите сохранить состояние, вы сериализуете объект (используя кодировку JSON и base64). Затем вы можете установить фрагмент href для этой строки.

var encodedState = base64(json(state));
var newLocation = oldLocationWithoutFragment + "#" + encodedState;

document.location = newLocation; // adds new entry in browser history
document.location.replace(newLocation); // replaces current entry in browser history

Первый способ будет рассматривать новое состояние как новое местоположение (поэтому кнопка «Назад» перенесет их в предыдущее место). Последнее нет.


источник
Есть ли способ добавить запись в историю закладок, не обновляя страницу? Установка местоположения (как в первом примере) приведет к обновлению, не так ли?
Дрю Ноакс
выполнение document.location.replace также перенаправит браузер на этот URL (только что попробовал его в консоли Chrome)
Omu
3

SWFAddress работает в проектах Flash и Javascript и позволяет вам создавать URL-адреса для закладок (используя метод хеширования, упомянутый выше), а также предоставляет вам поддержку кнопки назад.

http://www.asual.com/swfaddress/


источник
3

Метод window.location.hash является предпочтительным способом ведения дел. Для объяснения того, как это сделать, Ajax Patterns - Уникальные URL .

YUI имеет реализацию этого шаблона в виде модуля, который включает в себя определенные обходные пути для IE, чтобы заставить кнопку возврата работать вместе с перезаписью адреса с использованием хеша. YUI Browser History Manager .

Другие фреймворки также имеют аналогичные реализации. Важным моментом является то, что если вы хотите, чтобы история работала вместе с перезаписью адреса, различным браузерам нужны разные способы обработки. (Это подробно описано в первой статье.)

IE нужен хак на основе iframe, где Firefox будет создавать двойную историю, используя тот же метод.

Дрю Ноакс
источник
3

Если OP или другие пользователи все еще ищут способ изменить историю браузера, чтобы включить состояние, использование pushState и replaceState, как это предлагает IESUS, является «правильным» способом сделать это сейчас. Это главное преимущество по сравнению с location.hash, похоже, в том, что он создает реальные URL, а не просто хэши. Если история браузера, использующая хэши, сохраняется, а затем возвращается с отключенным JavaScript, приложение не будет работать, так как хэши не отправляются на сервер. Однако, если pushState был использован, весь маршрут будет отправлен на сервер, который вы затем сможете построить, чтобы соответствующим образом реагировать на маршруты. Я видел пример, когда одни и те же шаблоны усов использовались как на стороне сервера, так и на стороне клиента. Если бы у клиента был включен javascript, он получал бы быстрые ответы, избегая обращения к серверу, но приложение будет прекрасно работать без JavaScript. Таким образом, приложение может изящно ухудшаться при отсутствии javascript.

Кроме того, я полагаю, что есть какая-то инфраструктура с таким именем, как history.js. Для браузеров, которые поддерживают HTML5, он использует pushState, но если браузер не поддерживает это, он автоматически возвращается к использованию хэшей.

Нил
источник
2

Проверьте, находится ли пользователь на странице, когда вы нажимаете на строку URL, javascript говорит, что вы находитесь вне страницы. Если вы измените строку URL и нажмете «ENTER» с символом «#» внутри, то вы снова перейдете на страницу, не нажимая на страницу вручную с помощью курсора мыши, тогда команда события keyboad (document.onkeypress) из javascript будет быть в состоянии проверить, если он входит и активировать JavaScript для перенаправления. Вы можете проверить, находится ли пользователь на странице с помощью window.onfocus, и проверить, находится ли он с помощью window.onblur.

Да, это возможно.

;)

Marcelo
источник
Это элегантный способ изменить страницу, когда пользователь редактирует строку URL с символом #.
Марсело