Используем HTML5 History API

Здравствуйте, уважаемые читатели XoZbloga! Сегодняшняя статья будет посвящена работе с HTML5 History API. В прошлых версиях HTML у нас был ограниченный контроль над историей браузера. Мы могли перемещаться по истории вперед и назад с помощью доступных методов. Теперь, благодаря HTML5 History API, у нас есть больше возможностей использования истории браузера пользователя: можно «гулять» по истории, добавлять свои элементы в историю и обновлять текущую запись в истории.

Что это?

HTML5 History API представляет собой стандартизированный способ манипулировать историей браузера с помощью JavaScript. Часть этого API — навигация по истории, была доступна в предыдущих версиях HTML. В HTML5 включили возможность добавлять записи в историю браузера, чтобы визуально изменить URL в адресной строке браузера (без обновления страницы) и заменять текущую запись в истории браузера. Это означает, что URL в адресной строке браузера так и остается уникальным идентификатором для текущего ресурса, даже в приложениях с большим количеством скриптов, которые зачастую не выполняют полного обновления страницы.

Поддержка браузеров

На текущий момент данный API поддерживается множеством браузеров. Более подробно Вы можете узнать об этом здесь.
HTML5 History API поддержка браузерами
Чтобы программно определить, поддерживается ли API, используем:

1
return !!(window.history && history.pushState);

Если Вы пользуетесь Modernizr:

1
2
3
if (Modernizr.history) {
    // History API поддерживается
}

Если браузер не поддерживает 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) Метод добавляет запись в стек истории сеанса. Принимает три параметра:

  • data — данные записи в стеке истории. Эти данные могут использоваться в обработчике события popstate. Если никаких дополнительных данных передавать не требуется — указывается null;
  • title — заголовок страницы, можно указать null;
  • url — адрес страницы, может быть как относительным так и абсолютным.
window.history.replaceState(data,title,url) Метод аналогичный предыдущему, однако вместо добавления новой записи в стек, заменяется текущая запись.
popstate Обработчик события вызываемый при навигации по истории. Т.е. отрабатывает при нажатии на кнопки вперед/назад в браузере (в JavaScript- addEventListener) или при вызове методов back(), forward(), go(n).

Поведение методов replaceState и pushState можно отобразить следующим образом. Представим, что в нашем стеке истории есть 2 записи (помечены 1 и 2), и мы должны добавить третью (помечена 3). При использовании pushState запись добавляется в «стопку» записей над предыдущими, в то время как при использовании replaceState заменяется последняя запись (самая верхняя в «стопке»). Вся документация по этому API тут.

Разница методов replaceState и pushState

Простой пример использования

Давайте рассмотрим на примере работу с методом pushState. Допустим имеются 3 страницы почти с одинаковым содержанием. Разметка выглядит следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="container">
      <ul class="nav">
          <li><a href="index.html" class="historyAPI">Главная</a></li>
          <li><a href="about.html" class="historyAPI">О нас</a></li>
          <li><a href="contact.html" class="historyAPI">Контакты</a></li>
      </ul>
      <div>
          Нажмите на ссылки выше, чтобы использовать метод <strong>pushState</strong>.  
          <div class="jumbotron" id="contentHolder">
              <h1>Главная!</h1>
              <p>Здесь какой-то текст главной страницы.</p>
          </div>
      </div>
</div>

Вот как мы будем обрабатывать клики в меню:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$('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. Или скачать исходники и поэкспериментировать.

На этом все. Если Вы уже используете HTML5 History API, поделитесь в комментариях своим опытом. Спасибо за прочтение!

P.S.: Пожалуй, самым важным при создании сайта является подбор и регистрация доменного имени. Зачастую не просто найти хороший сервис для этого. Если Вы не знаете, как купить доменное имя by — не теряйте время, переходите по ссылке.

Чтобы оставаться в курсе свежих статей и уроков подписывайтесь на еженедельную почтовую рассылку или на новостную ленту RSS. Спасибо!