Здравствуйте, уважаемые читатели, в этой статье я хочу привести пример работы 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.