PHP

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

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

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

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

domain.com/about #portfolio=autor1
domain.com/about #portfolio=autor2

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

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

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



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

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

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

Пример History API + AJAX

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



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

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



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

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

Код файла index.php выглядит таким образом:
<!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 выглядит следующим образом:



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

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

Вот так выглядит скрипт script.js
$(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. Как бы это не было удивительно, но таких строк в файле всего несколько:
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:
history.replaceState({uri:thisUri}, null, thisUri);

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

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

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

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

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

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

Если к серверу пришел ajax запрос, а это значит, что каркас для вывода информации подготовлен, то нужно отдать только содержание.
Если же, средствами адресной строки браузера, произошло прямое обращение к странице page1.php, то файл подключит каркас приложения, и выводом информации займется уже script.js, который в свою очередь произведет запись в созданный браузером первый стейт, о том что запрашиваемый URI = page1.php, и отправит аякс запрос на сервер к нужной странице, т.е к page1.php, а дальше сработает первый пункт алгоритма.
Аналогично выглядит и работает файл page2.php:
<?php 
if($ajax) {
  echo "<span style='color:green'>Можете нажать кнопку \"Назад\" в браузере, чтобы убедиться в работоспособности History API</span>";
} else { 
  include 'index.php';
}

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

History API и IE < 10

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

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

Заключение

Я считаю, что с появлением History API сайты можно вывести на новый уровень, поскольку теперь все части контента можно загружать динамически, при этом полностью эмулируя переход по страницам, со сменой URL.
Теги:
History API
Добавлено: 29 Сентября 2013 08:25:27 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...