- history.pushState — not working?
- 2 Answers 2
- Работа с History API
- Добавление и изменение записей в истории
- Пример метода pushState()
- Метод pushState()
- Метод replaceState()
- Пример метода replaceState()
- Событие popstate
- Используем HTML5 History API
- Что это?
- Поддержка браузеров
- Методы и свойства API
- Простой пример использования
- Просмотр демо страницы и скачивание исходников не доступно
history.pushState — not working?
I want to change html without reload. I do it like:
It works correctly. But if I want to go back with «Back» button — browser change url on previous, but it not reload page. Why?
2 Answers 2
this behaviour is expected and is in accordance with the specifications of manipulating the history stack.
this is a relatively complex problem to explain. but in short think of it as this: any history entry the user pushes on the history stack (using pushState etc) doesn’t merit a page load when you move from it because it is considered a fake (user generated) history entry.
why? this behaviour is a good thing and is consistent with the intent of giving the developer more control over the page without being forced to reload it (think of it like ajax: you can do things that were previously only possible by page reloading like fetching data but now you can do it without reloading the page using the XMLHttpRequest object).. if you want to mimic the behaviour of reloading the page when clicking the back button.. you can simply call location.reload() when you handle the window.onpopstate event
how? this may be outside the scope of your question but i just wanted to put it there to describe what we’re talking about
let me explain by using an existing example here (excerpted text will be italicised):
Suppose http://mozilla.org/foo.html executes the following JavaScript:
This will cause the URL bar to display http://mozilla.org/bar.html, but won’t cause the browser to load bar.html or even check that bar.html exists.
think of it as that you are creating an entry in the history stack that is not associated with an actual page load.. rather a ‘fake’ page load (ie you are just using javascript to manipulate the dom and insert html)..
Suppose now that the user now navigates to http://google.com, then clicks back. At this point, the URL bar will display http://mozilla.org/bar.html, and the page will get a popstate event whose state object contains a copy of stateObj. The page itself will look like foo.html, although the page might modify its contents during the popstate event.
the point here is that bar.html is a fake history entry that sits on top of the original http://mozilla.org/foo.html.. so you will see on the url http://mozilla.org/bar.html but the contents will belong to foo (in this example notice that we didnt manipulate the content of the dom when we pushed bar.html.. if we did like in your example.. then that content will also show up). the key thing here is that the page reloads!.. because we are serving a page that has a genuin entry on the history stack (even if on the url.. we are displaying a url that is associated with a fake entry on the history stack).
also separate this discussion from the page manually handling the popstate event.. that’s a different story and will just complicate things.
If we click back again, the URL will change to http://mozilla.org/foo.html, and the document will get another popstate event, this time with a null state object. Here too, going back doesn’t change the document’s contents from what they were in the previous step, although the document might update its contents manually upon receiving the popstate event.
here.. the page will not load!.. that’s because we are making the transfer from a fake history stack entry to the real one (and the real one was already loaded in the previous step.. so the page reloaded and that’s it).
that’s it for the example. the concept is kind of hard to explain and i encourage you to test your code by clicking through a combination of real and fake pages and you will see a pattern of when the page actually loads and when it doesn’t..
Источник
Работа с History API
В HTML5 стали доступны методы pushState() и replaceState() для добавления и изменения записей в истории. Эти методы работают в сочетании с событием onpopstate (en-US)
Добавление и изменение записей в истории
pushState() позволяет изменить referrer, который используется в HTTP-заголовке для XMLHttpRequest объектов, созданных после изменения состояния. Значением referrer будет URL документа, окно которого является this на момент создания XMLHttpRequest объекта.
Пример метода pushState()
Предположим, на странице http://mozilla.org/foo.html выполняется следующий JavaScript-код:
В результате этого в URL-строке отобразится адрес http://mozilla.org/bar.html , но браузер не будет загружать страницу bar.html и даже не будет проверять, существует ли она..
Теперь предположим, что пользователь перешёл по адресу http://google.com и затем нажал на кнопку «Назад«. В результате этого в URL будет отображаться http://mozilla.org/bar.html , а history.state будет содержать stateObj . Событие popstate не будет вызвано, поскольку страница была перезагружена. Сама страница будет выглядеть как bar.html .
Если пользователь ещё раз нажимает кнопку «Назад», URL изменится на http://mozilla.org/foo.html , а в документе снова произойдёт событие popstate , на этот раз с объектом состояния, имеющим значение null . В этом случае возврат назад также не меняет содержимое документа, как и на предыдущем шаге, хотя документ может сам обновить своё содержимое после получения события popstate .
Примечание: Вызов history.back() обычно ведёт себя так же, как нажатие на кнопку «Назад». Но есть одно важное исключение:
После использования history.pushState() , вызов history.back() не вызывает событие popstate . Нажатие в браузере на кнопку «Назад» (всё ещё) делает это.
Метод pushState()
Метод pushState() принимает три параметра: объект состояния, заголовок (в данный момент игнорируется) и (необязательно) параметр «URL».
Давайте более подробно рассмотрим каждый и этих трёх параметров.
state object Объект состояния – это JavaScript-объект, связанный с новой записью в истории, созданной pushState() . Всякий раз, когда пользователь переходит к новому состоянию, происходит событие popstate , а свойство state этого события содержит копию объекта состояния с записями истории. Объект состояния может быть чем-угодно, что может быть сериализовано. Поскольку Firefox сохраняет объекты состояния на диске пользователя, чтобы их можно было восстановить после перезапуска браузера, мы накладываем ограничение в 640 тысяч символов на сериализованное представление объекта состояния. Если вы передаёте объект состояния, чьё сериализованное представление больше этого значения, метод pushState() выдаст исключение. Если вам нужно хранилище большего размера, следует рассмотреть использование sessionStorage и/или localStorage . title Заголовок — все браузеры, кроме Safari, на данный момент игнорируют этот параметр, но могут начать использовать в будущем. Ввиду будущих изменений метода, безопасным решением является передача пустой строки. В качестве альтернативы вы можете передать короткий заголовок для состоянии, в которое переходите. URL Через этот параметр передаётся URL-адрес новой новый записи в истории. Обратите внимание, что браузер не будет пытаться загрузить данный URL сразу после вызова pushState() , но может попытаться сделать это позже, например, после того, как пользователь перезапустит браузер. Новый URL-адрес не обязан быть абсолютным; если он относительный, то определяется относительно текущего URL. Новый URL должен вести на тот же домен, протокол и порт, иначе pushState() выдаст исключение. Данный параметр не является обязательным; если он не указан, будет использоваться URL текущего документа.
Вызов pushState() в некоторой степени похож на установку window.location = «#foo» , поскольку они оба также создают и активируют ещё одну запись в истории, связанную с текущим документом.
Но у pushState() есть несколько преимуществ:
- Новый URL может быть любым в пределах того же домена, порта и протокола, что и текущий адрес. Тогда как настройка window.location оставляет вас на том же document лишь в том случае, если вы меняете только хэш
- Менять URL не обязательно. Тогда как настройка window.location = «#foo»; создаёт новую запись в истории, только если текущий хеш не #foo
- С новой записью в истории можно связать любые данные. В подходе, основанном на хеше, все соответствующие данные нужно кодировать в короткую строку
- Если заголовок title впоследствии используется браузерами, эти данные могут быть использованы (независимо от, скажем, хеша).
Обратите внимание, что pushState() никогда не вызывает событие hashchange , даже если новый URL отличается от старого только хешем.
В XUL-документах он создаёт указанный XUL-элемент
В других документах он создаёт элемент с null namespace URI.
Метод replaceState()
history.replaceState() работает точно так же, как history.pushState() , за исключением того, что replaceState() изменяет текущую запись истории вместо создания новой записи. Обратите внимание, что он не предотвращает создание новой записи в глобальной истории браузера.
replaceState() особенно полезен, когда вы хотите обновить объект состояния или URL текущей записи в истории в ответ на какое-то действие пользователя.
Пример метода replaceState()
Предположим, на странице http://mozilla.org/foo.html выполняется следующий JavaScript-код:
Объяснение этих двух строк можно найти в приведённом выше разделе пример метода pushState().
Далее, предположим, на странице http://mozilla.org/bar.html выполняется JavaScript-код:
Это приведёт к тому, что в URL-строке отобразится адрес http://mozilla.org/bar2.html , но браузер не станет сразу загружать bar2.html и даже не станет проверять наличие этой страницы bar2.html .
Теперь предположим, что пользователь переходит по адресу http://www.microsoft.com , а затем нажимает на кнопку «Назад». В этом случае в URL-строке отобразится http://mozilla.org/bar2.html . Если же пользователь снова нажмёт на кнопку «Назад», в URL-строке отобразится http://mozilla.org/foo.html и полностью обойдёт bar.html .
Событие popstate
Событие popstate вызывается в окне каждый раз, когда активная запись в истории меняется. Если запись в истории, которая активируется, была создана с помощью вызова pushState или активирована вызовом replaceState , свойство state события popstate содержит копию записи в истории объекта события.
Источник
Используем HTML5 History API
Здравствуйте, уважаемые читатели XoZbloga! Сегодняшняя статья будет посвящена работе с HTML5 History API. В прошлых версиях HTML у нас был ограниченный контроль над историей браузера. Мы могли перемещаться по истории вперед и назад с помощью доступных методов. Теперь, благодаря HTML5 History API, у нас есть больше возможностей использования истории браузера пользователя: можно «гулять» по истории, добавлять свои элементы в историю и обновлять текущую запись в истории.
Что это?
HTML5 History API представляет собой стандартизированный способ манипулировать историей браузера с помощью JavaScript. Часть этого API — навигация по истории, была доступна в предыдущих версиях HTML. В HTML5 включили возможность добавлять записи в историю браузера, чтобы визуально изменить URL в адресной строке браузера (без обновления страницы) и заменять текущую запись в истории браузера. Это означает, что URL в адресной строке браузера так и остается уникальным идентификатором для текущего ресурса, даже в приложениях с большим количеством скриптов, которые зачастую не выполняют полного обновления страницы.
Поддержка браузеров
На текущий момент данный API поддерживается множеством браузеров. Более подробно Вы можете узнать об этом здесь.
Чтобы программно определить, поддерживается ли API, используем:
Если Вы пользуетесь Modernizr:
Если браузер не поддерживает API или Вы ищете кроссбраузерное решение, то можно использовать плагин history.js. Построен на основе HTML5 History API и использует те же самые методы, в то же время можно не беспокоиться о работоспособности в старых браузерах.
Методы и свойства API
Новые возможности HTML5 по управлению историей браузера позволяют реализовать такой подход, при котором мы можем загружать только те части страницы, которые изменяются по сравнению с предыдущими (при навигации по сайту). Это позволит существенно сэкономить трафик и повысить скорость выполнения запросов пользователей. Например, загружать только текст статей, а стили и скрипты не трогать.
Далее приведена таблица с описанием основных свойств и методов рассматриваемого API.
| Метод/свойство | Описание |
| window.history.length | Возвращает количество записей в текущей истории сеанса. |
| window.history.state | Возвращает текущую запись из стека истории. |
| window.history.go(n) | Метод позволяется перемещать по текущей истории сеанса вперед (если значение n со знаком плюс) или назад (если значение n со знаком минус) на заданное число шагов. Например window.history.go(+2) . При нулевом n произойдет обновление текущей страницы. Если n находится вне диапазона, ничего не произойдет. |
| window.history.back() | Возврат на один шаг назад в истории сеанса. Если предыдущих записей в стеке истории нет, ничего не произойдет. Аналогичен window.history.go(-1) . |
| window.history.forward() | Вперед на один шаг в истории сеанса. Если последующих записей в стеке истории нет, ничего не произойдет. Аналогичен window.history.go(+1) . |
| window.history.pushState(data,title,url) | Метод добавляет запись в стек истории сеанса. Принимает три параметра:
|
| window.history.replaceState(data,title,url) | Метод аналогичный предыдущему, однако вместо добавления новой записи в стек, заменяется текущая запись. |
| popstate | Обработчик события вызываемый при навигации по истории. Т.е. отрабатывает при нажатии на кнопки вперед/назад в браузере (в JavaScript- addEventListener ) или при вызове методов back(), forward(), go(n). |
Поведение методов replaceState и pushState можно отобразить следующим образом. Представим, что в нашем стеке истории есть 2 записи (помечены 1 и 2), и мы должны добавить третью (помечена 3). При использовании pushState запись добавляется в «стопку» записей над предыдущими, в то время как при использовании replaceState заменяется последняя запись (самая верхняя в «стопке»). Вся документация по этому API тут.
Простой пример использования
Давайте рассмотрим на примере работу с методом pushState. Допустим имеются 3 страницы почти с одинаковым содержанием. Разметка выглядит следующим образом:
Вот как мы будем обрабатывать клики в меню:
$ ( ‘document’ ) . ready ( function ( ) <
$ ( ‘.historyAPI’ ) . on ( ‘click’ , function ( e ) <
// отменяем стандартное действие при клике
e. preventDefault ( ) ;
// Получаем адрес страницы
var href = $ ( this ) . attr ( ‘href’ ) ;
// Передаем адрес страницы в функцию
getContent ( href , true ) ;
> ) ;
> ) ;
// Добавляем обработчик события popstate,
// происходящего при нажатии на кнопку назад/вперед в браузере
window. addEventListener ( «popstate» , function ( e ) <
// Передаем текущий URL
getContent ( location. pathname , false ) ;
> ) ;
// Функция загрузки контента
function getContent ( url , addEntry ) <
$. get ( url ) . done ( function ( data ) <
// Обновление только текстового содержимого в сером блоке
$ ( ‘#contentHolder’ ) . html ( $ ( data ) . find ( «#contentHolder» ) . html ( ) ) ;
// Если был выполнен клик в меню — добавляем запись в стек истории сеанса
// Если была нажата кнопка назад/вперед, добавлять записи в историю не надо
if ( addEntry == true ) <
// Добавляем запись в историю, используя pushState
history. pushState ( null , null , url ) ;
>
> ) ;
>
Вы можете перейти на демонстрационную страницу, чтобы наглядно посмотреть как все происходить при использовании метода pushState. Или скачать исходники и поэкспериментировать.
Просмотр демо страницы и скачивание исходников не доступно
Уважаемый читатель, XoZblog существует и развивается за счёт доходов от ненавязчивой рекламы. Если не затруднит, добавьте этот сайт в исключение AdBlock. Спасибо за понимание!
На этом все. Если Вы уже используете HTML5 History API, поделитесь в комментариях своим опытом. Спасибо за прочтение!
P.S.: Пожалуй, самым важным при создании сайта является подбор и регистрация доменного имени. Зачастую не просто найти хороший сервис для этого. Если Вы не знаете, как купить доменное имя by — не теряйте время, переходите по ссылке.
Чтобы оставаться в курсе свежих статей и уроков подписывайтесь на еженедельную почтовую рассылку или на новостную ленту RSS. Спасибо!
Источник