Статьи

Мобильные веб-приложения: Ajax

Вы не поверите, что это пятая выдержка из книги Эрла Кастледина , Майлса Эфтоса и Макса Уилера « Создание мобильных веб-сайтов и приложений для интеллектуальных устройств ». BuildMobile публикует главу «Мобильные веб-приложения» из книги, этот раздел называется «Ajax», и он становится серьезным.

5. Аякс

Теперь мы научились плавно переходить между страницами без перезагрузки, но до сих пор мы делали это только со статическим контентом. Нам нужно иметь возможность загружать наши страницы динамически, а затем переходить к ним.

Хорошей новостью является то, что Ajax обладает сравнительно отличной поддержкой на мобильных устройствах высокого класса, поэтому работа с Ajax остается в основном такой же, как и на настольных ПК. Конечно, вы должны учитывать, что среднее соединение для передачи данных будет на порядок медленнее (и дороже), поэтому лучше всего поддерживать использование полосы пропускания на абсолютном минимуме.

Есть два подхода к загрузке динамических данных в наше приложение. Мы можем загрузить необработанные данные (например, список объектов JSON, представляющих недавно обнаруженных знаменитостей) и объединить их с HTML-кодом приложения, создав элементы списка и добавив их на страницу. Или мы могли бы загрузить все содержимое HTML прямо с сервера и поместить его прямо на нашу страницу. Последний подход звучит проще: давайте попробуем сначала познакомиться с Ajax в мобильной среде. После этого мы рассмотрим обработку других форматов данных.

5.1. Извлечение HTML

Первое, что нам нужно, если мы хотим получить данные с сервера, это … сервер! Если вы попытаетесь получить данные из URL-адреса протокола file:// (что будет иметь место, если вы тестируете страницы, дважды щелкнув файл index.html ), вы получите ужасный «Access-Control-Allow- Происхождение »ошибка.

Серверы

Так как это книга о создании мобильных веб-приложений на HTML, CSS и JavaScript, в которой подробно рассматриваются вопросы настройки сервера для доставки ваших данных, к сожалению, за пределами нашей компетенции. Мы проведем оставшуюся часть этой главы, рассматривая примеры функций Ajax, которые мы можем добавить в Startrackr, но если вы хотите попробовать эти примеры для себя, вам нужно настроить сервер для доставки соответствующих данных.

Предполагая, что у нас есть сервер — будь то на нашей машине локально, на виртуальной машине или в Интернете — теперь нам нужно куда-то выгружать фрагменты HTML, когда они возвращаются с сервера. Для этого нам нужен только скелет страницы, с которой мы работали, чтобы он работал как контейнер, который мы заполняем. Поскольку мы будем возвращать ту же разметку, что и раньше, наш оригинальный CSS будет применяться к содержимому без необходимости его изменения. Вот этот скелет:

Пример 4.52. ch4/13-ajax.html (отрывок)

 <div id="pages"> <div id="page-spots" class="page-spots"></div> <div id="page-spot" class="page-spots"></div> <div id="page-sightings" class="page-sightings"></div> <div id="page-stars" class="page-stars"></div> <div id="page-star" class="page-stars"></div> </div> 

Все содержимое каждого из этих разделов находится в spots.html , new.html и stars.html — как обычный веб-сайт, за исключением того, что теперь мы будем использовать Ajax для загрузки этого содержимого в этот пустой скелет.

С этим базовым HTML на следующем шаге нужно остановить переход по ссылке при щелчке, как мы делали ранее с нашей функцией перехода — с помощью preventDefault() . Тогда мы можем выполнить наш Ajax. Функция jQuery load() идеально подходит для наших нужд: она загружает HTML из URL-адреса и предоставляет механизм выбора части документа для возврата. Это здорово, потому что нам не нужна вся страница с заголовками и метатегами — нам нужно только содержимое body . Использование load() означает, что нам не нужна специальная версия нашей HTML-страницы для Ajax, и любые обновления должны производиться только в одном месте.

Для этого мы используем функцию load() со строковым параметром, состоящим из требуемого URL-адреса, за которым следует пробел, за которым следует строка селектора jQuery. Содержимое элемента, соответствующего этому селектору, будет вставлено в элемент, из которого была вызвана load() . Содержимое, которое мы хотим вставить, содержится в .wrapper div целевой страницы. Итак, когда щелкают ссылку Spots, мы хотим вызвать load() для нашего контейнера #spots и передать строку «spot.html .wrapper»:

Пример 4.53. javascripts/ch4/13-ajax.js (отрывок)

 $("#tab-spots a").click(function(e){ e.preventDefault(); $("#page-spots").load("spots.html .wrapper"); }); 

Загрузка фрагментов HTML

Если вы не знакомы с jQuery, вам может быть интересно, как он загружается в небольшой раздел HTML через Ajax. Здесь нет магии; он фактически загружает всю страницу и выгружает ее в элемент div который существует вне DOM. Фильтрация выполняется для этого элемента, и результаты вставляются в правильное положение. Очень удобно, хотя, конечно, это означает передачу большего количества данных по сети, чем вы фактически используете. Для большинства реальных приложений вы, вероятно, захотите извлечь данные в формате XML или JSON и вставить их в свой HTML на стороне клиента. Мы посмотрим, как это можно сделать в ближайшее время. Однако пока мы будем придерживаться использования load() чтобы упростить его, и сосредоточимся на демонстрации того, как работают различные методы Ajax, а также того, как их лучше всего использовать в контексте мобильного приложения.

Это загрузит соответствующий HTML-код в нужный контейнер, но есть еще несколько задач, на которые нужно обратить внимание, в частности, сделать новый контент видимым! К счастью, load() позволяет вам указать функцию обратного вызова, которая будет выполняться после завершения вызова Ajax. Внутри этого обратного вызова мы переведем страницу в представление:

Пример 4.54. javascripts/ch4/13-ajax.js (отрывок)

 $("#tab-spots a").click(function(e){ e.preventDefault(); $("#page-spots").load("spots.html .wrapper", function() { transition('#page-spots', "fade", false); }); }); 

Добавление событий к каждому элементу навигации — утомительный способ подключить наш сайт. Мы только что создали Ajax-загрузчик для страницы Spots, но нам пришлось бы дублировать этот код несколько раз, чтобы он работал для всех ссылок. Вместо этого мы можем воспользоваться преимуществами последовательной структуры нашего сайта и придумать систему, чтобы сделать это программно, на основе содержимого элементов навигации. Это дает нам прогрессивный уровень улучшения: наши ссылки разработаны для нормальной работы, но наша система перехватывает их при нажатии и загружает контент через Ajax. Этот метод иногда называют Hijax .

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

Пример 4.5 ### 5. javascripts/ch4/14-hijax.js (отрывок)

 function loadPage(url, pageName) { $("#" + pageName).load(url + " .wrapper", function(){ console.log(this); transition("#" + pageName, "fade", false); }); }; 

Эта функция практически идентична предыдущему коду, за исключением того, что мы заменили имена страниц и URL-адреса переменными. Теперь мы можем загрузить страницу программно, например:

loadPage («spot.html», «spot»);
На самом деле, нам нужно загружать страницу по умолчанию при загрузке приложения, чтобы мы могли поместить эту строку кода в обработчик document.ready . Это загрузит страницу Спотов через Ajax в качестве нашей домашней страницы.

Кеширование данных

Поскольку метод load() извлекает весь HTML-файл, результаты могут кэшироваться браузером, что означает, что изменения, внесенные в загружаемую страницу, могут не отражаться сразу. Вы можете отключить кэш глобально (для всех запросов Ajax) с помощью $.ajaxSetup({ cache: false }); или, если это только для одного конкретного вызова, вы можете добавить временную метку к URL, чтобы каждый запрос был воспринят браузером как различный. Таким образом, вместо загрузки url + " #wrapper" , вы можете загрузить url + "?" + new Date().getTime() + " #wrapper" url + "?" + new Date().getTime() + " #wrapper" .

Наконец, мы хотим вызывать нашу функцию всякий раз, когда нажимаются какие-либо элементы навигации. Помните, мы должны извлечь две части данных для передачи нашей функции: URL-адрес и имя страницы. URL-адрес прост — это значение href самой ссылки. Что касается имени страницы, есть много подходов, которые мы могли бы использовать: мы могли бы дать нашим контейнерам те же имена, что и файлы (за исключением .html ), или мы могли бы добавить некоторые дополнительные данные в саму ссылку. Последнее стало проще с добавлением пользовательских атрибутов данных в HTML5, которые позволяют аннотировать элементы парами ключ / значение:

Пример 4.56. ch4/14-hijax.html (отрывок)

 <ul id="tab-bar"> <li> <a data-load="spots" href="spots.html">Spots</a> </li> <li> <a data-load="sightings" href="new.html">Add a sighting</a> </li> <li> <a data-load="stars" href="stars.html">Stars</a> </li> </ul> 

Атрибут данных начинается с data- и сопровождается вашим именем ключа. Затем вы можете предоставить ему любое значение. Согласно спецификации, эти значения должны быть получены с использованием свойства набора данных элемента; однако, это еще не получило широкой поддержки, поэтому лучше всего использовать стандартную getAttribute() (например, myElement.getAttribute("data-load") ), или, если вы используете jQuery, attr() метод:

Пример 4.57. javascripts/ch4/14-hijax.js (отрывок)

 $("#tab-bar a").click(function(e){ e.preventDefault(); var url = e.target.href; var pageName = $(this).attr("data-load"); loadPage(url, pageName); }); 

И вуаля! Любая ссылка внутри элемента #tab-bar запустит нашу loadPage() , и мы перейдем с текущей страницы на новую. Вы можете легко расширить эту систему, чтобы также указать тип перехода, если хотите.

Одной из текущих проблем является то, что если загрузка страницы занимает много времени, пользователь не имеет представления о том, что происходит (и он, вероятно, станет доволен кликом и попытается загрузить другую страницу). Очевидное решение — индикатор «загрузки»; Перейдите к главе 6, «Полировка нашего приложения», если вы хотите добавить его сейчас…

[ Ред . : что означает, что вы можете либо купить книгу «Создание мобильных веб-сайтов и приложений для интеллектуальных устройств», либо подождать, пока мы не выпустим Раздел 6 главы 4, «Подготовка нашего приложения» в будущем.]

Сборка мобильной книги

Вы можете приобрести книгу « Создание мобильных веб-сайтов и приложений для интеллектуальных устройств » в Sitepoint. Прочитайте всю главу 4. Мобильные веб-приложения , бесплатно здесь, в BuildMobile, бесплатно в следующих разделах.