Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%

<<< Js include и Js require || Как работать с vk API вконтакте >>>

History API, пример одностраничного приложения

05.03.2013
History API, пример одностраничного приложения

Здравствуйте, уважаемые читатели блога LifeExample, в этой статье я хочу привести пример работы c новой web-технологией: History API. При динамическом обновлении контента страницы, с помощью History API можно менять и адрес в строке браузера. Таким образом создав логику одностраничного приложения с использованием технологии AJAX в купе с History API, теперь можно не боятся, что данные не будут проиндексированы поисковиками. Сама технология History API стала доступна с появлением браузеров с поддержкой HTML5, но не торопитесь думать, что браузеры поддерживающие только HTML4 останутся за бортом. Для старых браузеров существует специальная JS библиотека позволяющая работать с History API.

Что нам дает History API + AJAX

Раньше программируя логику для работы с динамическим контентном мы использовали символ "#" чтобы менять url и иметь возможность обмениваться ссылками. И все бы ничего, но поисковые роботы не учитывают то, что встречается после "#". Другими словами в глазах робота две ссылки:

  • Lifeexample.ru/about #portfolio=autor1
  • Lifeexample.ru/about #portfolio=autor2

Будут выглядеть одинаково: Lifeexample.ru/about, соответственно и весь контент на этих страницах не будет проиндексирован, а это совершенно не годится для разработки сайтов.

Используя history api мы с легкостью можем динамически подгружать те части страницы которые нам требуется и изменять ссылки в браузере.

Попробую объяснить общую концепцию построения информационного сайта с использованием связки AJAX и history api.

history-api-на-примере

На иллюстрации выделено три области:

  1. Браузерная строка;
  2. Место для отображения динамически меняющегося контента;
  3. Не динамическая облась (все что загружается только один раз)

Суть работы сайта, в котором используется History API + AJAX, заключается в том, что единожды загрузив все, область помеченную цифрой 3, мы больше этот контент не трогаем, а обновляем только динамическую часть. Такой подход позволяет в разы увеличить юзабилити сайта и скорость его работы.

Думаю с задачей и ее смыслом стало чуть яснее, и самое время перейти к реализации этой концепции.

Пример History API + AJAX

Если вы думает, что реализовать задуманное будет очень сложно, то вы ошибаетесь, если хорошо знать принцип работы AJAX приложения, то прикрутить к этому History API будет очень просто. Для демонстрации работоспособности данных технологий нам понадобится создать всего четыре PHP файла и каталог для хранения скриптов.

файлы для демонстрации history-api

Коротко опишу, что из себя должны представлять эти файлы.

  • ajax.php – как следует из названия, является маршрутизатором ajax запросов.
  • index.php – задает основную разметку приложения, подгружая статичную часть сайта.
  • page1.php и page2.php – файлы содержащие динамический контент.

В каталог JS мы положим два файла, один управляющий JS скрипт, в котором реализуем всю логику приложения и второй – библиотеку jQuery для удобства работы с ajax технологией .

js-скрипты-для-ajax-и-history-api

На картинке вы видите и третий JS файл history – являющийся библиотекой для работы history API в старых браузерах, он пригодится нам чуть позже для приручения IE7-IE9.

Содержание файлов

Код файла index.php выглядит таким образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />      
        <script type="text/javascript" src="/js/jquery-1.9.0.min.js"></script>
        <script type="text/javascript" src="/js/script.js"></script>       
    </head>
    <body>
        <!--Блок ссылок для переключения страниц-->
        <div id='control'>
            <a href="page1.php">Показать страницу 1</a>
            <a href="page2.php">Показать страницу 2</a>
        </div>     
       
        <div id='data'>
        <!--Блок для вывода динамического контента-->
        </div> 
       
        <!--Таймер для демонстрации динамического обновления данных-->   
        <div id='timer'>0</div>        
    </body>
</html>

Все что делает index.php это формирует три блока для отображения контента.

  • Блок ссылок для переключения страниц;
  • Блок для вывода динамического контента;
  • Таймер для демонстрации динамического обновления данных;

Интерфейс сформированный в index.php выглядит следующим образом:

интерфейс примера history-api

Как видно из рисунка, интерфейс имеет две ссылки переключающие страницы, таймер (число 2 в конце интерфейса) и блок для динамического контента , который выделен красным. Это все что требуется для демонстрации примера.

Также в index.php подключается jQuery библиотека и скрипт script.js управляющий выводом страниц, в динамическую область, используя History API.

Вот так выглядит скрипт script.js

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
$(document).ready(function(){

    // получаем текущий uri, если uri не существует то присваиваем uri первой страницы
    var thisUri = getThisUri()?getThisUri():'page1.php';
   
    //сразу задаем параметры для текущего состояния
    history.replaceState({uri:thisUri}, null, thisUri);
   
    // клик на ссылки переключения страниц
    $('#control a').click(function(){    
   
      // получем путь к запрашиваемой странице
      var uri = $(this).attr('href');
     
      //создаем новую запись в истории только когда кликаем по ссылке
      history.pushState({uri:uri}, null, uri);
     
      // открываем страницу
      openPage(uri);     
      return false;
    });
   
    // обработчик нажатий на кнопки браузера назад/вперед
    $(window).bind('popstate', function(event) {
      openPage(history.state.uri); 
    });

    /**
     * Загрузка запрашиваемых страниц с сервера
     */

    function openPage(uri){
    // динамическая загрузка контента
      $.ajax({
        type: "POST",
        url: "/ajax.php",
        data: {
          uri: uri
        },
        cache: false,        
        success: function(data){  
          // вывод в блок <div id="data">
          $('#data').html(data);
        }
      });
    }
   
    /**
     * Возвращает текущий URI страницы
     */

    function getThisUri(){
       var loc = event.location
        || ( event.originalEvent && event.originalEvent.location )
        || document.location;      
        return loc.pathname.substr(1);
    }    

    // Вывод таймера в конце страницы
    var sec = 0;
    function incSec() {
      $('#timer').text(sec++);
    }
    setInterval(incSec, 1000);
});

Собственно этот файл является сердцем данного примера в использовании history API. Поскольку именно здесь происходит маршрутизация запросов на сервер в соответствии с выбранной страницей. И вывод полученной информации в нужное место.

По комментариям в коде становится ясной логика работы скрипта, поэтому я заострю внимание именно на строках относящихся к работе с history API. Как бы это не было удивительно, но таких строк в файле всего несколько:

1
history.pushState({uri:uri}, null, uri);

данной записью происходит установка нового состояния (State).

В рамках данной тематики State является некой сущностью, создающейся при переходе от одной странице сайта к другой. Браузер самостоятельно создает стэйты и ложит их в историю перемещения по страницам, чтобы использовать системные кнопки: "вперед" и "назад".

До недавнего времени повлиять из JS на историю стэйтов было невозможно, но с помощью history API это стало доступно. И смысл этой технологи заключается как раз в управлении, изменении и редактировании истории переходов.

Функйия history.pushState(param1,param2,param3) добавляет в стэк истории стэйтов новое состояние, при этом можно для нового состояния задать несколько параметров

  • param1 – произвольный объект, содержащий любую информацию, для работы приложения. В нашем примере я сохраняю в каждый стейт URI открытой страницы, чтобы считать его в будущем и сделать необходимую операцию на AJAX
  • param2 – title страницы , например "Главная страница".
  • param3 – uri который будет отображаться в адресной строке, сразу после установки стэйта.

В приведенном коде можно найти еще один метод относящийся к history API:

1
history.replaceState({uri:thisUri}, null, thisUri);

Исходя из названия, не сложно догадаться, что он занимается заменой параметров для текущего состояния. Обычно он является полезным, а в данном примере и необходимым, для изменения параметров первого стэйта в истории, потому что при первом заходе на сайт созданный браузером стэйт не имеет информации нужной для работы нашего приложения.

Из не рассмотренных остались еще три файла

ajax.php:

1
2
3
4
5
6
<?php
// Подгружает страницу указаную в $_POST['uri']
$ajax = true;
if(!empty($_POST['uri'])){
  include $_POST['uri'];
}

Этими не хитрыми строками происходит открытие нужных страниц сайта.

page1.php:

1
2
3
4
5
6
<?php
if($ajax) {
  echo "<span style='color:blue'>Динамически подгружаемый контент, в рамках урока по History API от lifeexample.ru</span>";
} else{
  include 'index.php';
}

Этот файл выводит на экран динамически подгружаемый контент либо верстку интерфейса приложения в зависимости от двух ситуаций.

  1. Если к серверу пришел ajax запрос, а это значит, что каркас для вывода информации подготовлен, то нужно отдать только содержание.
  2. Если же, средствами адресной строки браузера, произошло прямое обращение к странице page1.php, то файл подключит каркас приложения, и выводом информации займется уже script.js, который в свою очередь произведет запись в созданный браузером первый стейт, о том что запрашиваемый URI = page1.php, и отправит аякс запрос на сервер к нужной странице, т.е к page1.php, а дальше сработает первый пункт алгоритма.

Аналогично выглядит и работает файл page2.php:

1
2
3
4
5
6
<?php
if($ajax) {
  echo "<span style='color:green'>Можете нажать кнопку \"Назад\" в браузере, чтобы убедиться в работоспособности History API</span>";
} else {
  include 'index.php';
}

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

Скачать все исходники примера ( Скачали: 808 чел. ) 

History API и IE < 10

Как я упомянул выше, нам потребуется использовать библиотеку history.js, для того чтобы старые браузеры такие как Internet Explorer могли работать с технологией History API.

Поскольку IE, полноценно , поддерживает HTML 5 только с 10 версии, то все его предшественники не поймут методов history.pushState и history.replaceState потому как не имеют объекта history.

Заключение

Я считаю, что с появлением History API сайты можно вывести на новый уровень, поскольку теперь все части контента можно загружать динамически, при этом полностью эмулируя переход по страницам, со сменой URL.

Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.

Нравится

Комментарии

  • Сергей

    Здесь наверно ошибка Mozila firebug Ругается на эту строчку может window.location ?

    1
    var loc = event.location
  • AkidSe

    Здравствуйте. Сделал такое себе на сайт. НО при переходах по ссылках возникает проблема. Если переходить по свежим DOM-ссылкам — все нормально. А со старыми DOM-ссылками, что не обновляються происходит следуещее: загрузка страницы в ссылке загружаеться ровно столько же раз сколько я и сделал ajax-переходов.
    Что делать, как исправить?

  • Увидел «библиотеку jQuery для удобства работы с ajax технологией» сразу понял что читать эту статью нет смысла. Во первых ajax — не технология. Во вторых использование jQuery там где это не нужно показатель неграмотности.

    • Ну и что же такое AJAX по вашей версии ? )
      Использовать jQuery там где нужно решает только разработчик, и по этому нельзя судить о грамотности или не грамотности, зависит от сложности задачи.
      Это всего лишь инструмент для работы.

  • Оставить комментарий

    Подписаться на комментарии к этой статье по RSS

    Яндекс.Метрика