Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax_v_deystvii.pdf
Скачиваний:
38
Добавлен:
05.03.2016
Размер:
5.83 Mб
Скачать

Глава 4. Web-страница в роли приложения 169

Модифицированный вариант HTML-документа показан в листинге 4.9.

ЛИСТИНГ4.9. Документ mousemat.html, использующий объект EventRouter

<html> <head> <link rel='stylesheet' type='text/ess1 href='mousemat.ess' /> <script

type='text/javascript'

src='extras-array.js'X/script> <script

type='text/javascript'

src='eventRouter.js'X/script> <script

t ype='text/javascript'>

var cursor=null;

window.onload=function(){

var mat=document.getElementById('mousemat'); cursor=document.getElementById('cursor' ) ;

var mouseRouter=new jsEvent.EventRouter(mat,"onmousemove") ;

mouseRouter.addListener(writeStatus) ; mouseRouter.addListener(drawThumbnail);

}function writeStatus(e){ window.status=e.clientX+","+e.clientY

}function drawThumbnail(e){

cursor.style.left-((e.clientX/5)-2)+"px"; cursor.style.top=((e.clientY/5)-2)+"px";

} </script> </head> <body> <div class='mousemat' id='mousemat'x/div> <div class=' thumbnail' id='thumbnail'>

<div class='cursor1

id='cursor'/> </div> </body> </html>

Встроенный код JavaScript существенно упрощен. В данном случае нам надо лишь создать объект EventRouter, передать ему функции обработки и реализовать эти обработчики. Дальнейшим развитием документа и поддерживающего его кода может стать включение флажков опций, посредством которых пользователь сможет динамически добавлять или удалять обработчики. Мы предлагаем читателю самостоятельно реализовать данную возможность.

На этом мы заканчиваем обсуждение уровня контроллера в Ajaxприложении и роли, которую образы разработки, в частности Observer, играют в создании понятного и пригодного для сопровождения кода. В следующем разделе мы рассмотрим последний элемент архитектуры MVC — модель.

4.4. Модель в составе Ajax-приложения

Модель представляет собой область применения приложения — интерактивный магазин, музыкальный инструмент и даже набор точек в пространстве. Document Object Model, или DOM, не является моделью Ajaxприложения. В данном случае роль модели выполняет код, написанный на языке JavaScript. Подобно другим образам разработки, архитектура MVC неразрывно связана с объектным подходом.

170 Часть II. Основные подходы к разработке приложений

Разработчики JavaScript не задумывали его как объектно-ориентирован- ' ный язык, однако в нем, не затрачивая слишком много усилий, можно организовать некоторое подобие объектов. Посредством механизма прототипов можно определить нечто, похожее на классы, а некоторые разработчики пытаются даже реализовать наследование. Эти вопросы мы обсудим в приложении Б. До сих пор, создавая на JavaScript приложение, соответствующее архитектуре "модель-представление-контроллер", мы придерживались сти-Г ля программирования, типичного для JavaScript, например, передавали объекты Function непосредственно обработчикам событий. Определяя модель, желательно использовать объекты JavaScript и придерживаться объектного подхода настолько, насколько это имеет смысл для данного языка. В последующих разделах мы покажем, как это можно сделать.

4.4.1. Использование JavaScript для моделирования предметной области

Обсуждая представление, мы все время упоминали элементы DOM. Говоря о контроллере, мы были ограничены рамками модели событий, реализованной в браузере. При создании модели мы будем иметь дело почти исключительно с кодом JavaScript и практически не будем учитывать возможности браузеров. Для тех программистов, которые вынуждены постоянно бороться с несовместимостью браузеров, подобные условия работы покажутся предельно комфортными.

Рассмотрим простой пример. В главе 3 обсуждалось приложение для интерактивного магазина, а внимание в основном уделялось генерации данных серверными программами. Эти данные определяли товары в терминах идеи-; тификаторов, имен и описаний. Кроме того, учитывались цена, цвет и размер. Вернемся к данному примеру и рассмотрим, что произойдет, когда информация будет доставлена клиенту. В процессе работы приложение получает несколько подобных потоков данных и должно хранить их в памяти. Область памяти для хранения данных можно рассматривать как кэш на стороне клиента. Есть возможность быстро отобразить находящуюся в нем информацию, не обращаясь к серверу. О преимуществах такого подхода см. в главе 1.

Определим простой JavaScript-объект, соответствующий изделию, поддерживаемому сервером. Пример такого объекта приведен в листинге 4.10.

Листинг 4.10. Файл Garment, js

var garments=new Array(); function Garment(id,title,description,price){

t h i s . i d = i d ; garments[id]=this; this.title=title; this.description=description; this.price=price; this.colors=new Object(); this.sizes=new Object();

}

Garment.prototype.addColor(color){

Глава 4. Web-страница в роли приложения

171

t h i s . c o l o r s . a p p e n d ( c o l o r , t r u e ) ; } G a r m e n t . p r o t o t y p e . a d d S i z e ( s i z e ) {

t h i s . s i z e s . a p p e n d ( s i z e , t r u e ) ; )

Для хранения информации об изделиях определен глобальный массив. (Вы скажете, что использование глобальных переменных — плохой стиль программирования, и будете правы. При разработке реальных продуктов для этой цели обычно используются объекты пространств имен, однако в данном случае мы не будем поступать так, чтобы неоправданно не усложнять программу.) Это ассоциативный массив, для которого ключевыми значениями являются идентификаторы изделий. Такой подход гарантирует, что в каждый конкретный момент времени будет отображаться только одна ссылка на каждый тип товара. Все простые свойства, не являющиеся массивами, задаются в конструкторе. В момент определения массивы пусты. Для включения в них элементов используются специальные методы, которые обращаются к расширенному коду поддержки массивов (подробнее об этом — в приложении Б). Это также позволяет исключить дублирование данных.

Мы не создаем get- и set-методы и не реализуем полный контроль доступа посредством определения областей видимости для переменных и методов, что позволяют сделать объектно-ориентированные языки. Существуют способы обеспечения таких возможностей (они будут обсуждаться в приложении Б), но сейчас мы предпочитаем сделать модель как можно более простой.

При разборе потока XML-данных целесообразно сначала создать пустой объект Garment, а затем заполнять его информацией. Некоторые читатели удивятся, почему мы не предусмотрели более простой конструктор. На самом деле мы сделали это. Функции JavaScript позволяют задавать переменное количество параметров; недостающие параметры заменяются значениями null. Таким образом, два приведенных ниже вызова эквивалентны.

var garment=new Garment(123);

var garment=new Garment(123,null,null,null);

Идентификатор задавать необходимо, поскольку он используется в конструкторе для включения нового объекта в глобальный список изделий.

4.4.2. Взаимодействие с сервером

Для того чтобы генерировать объекты Garment в клиентской программе, нам надо организовать разбор XML-данных. О разборе мы уже говорили в главе 2, кроме того, мы вернемся к этому вопросу в главе 5, поэтому сейчас не будем детально обсуждать этот процесс. XML-документ содержит дескрипторы, атрибуты и содержимое элементов. Для чтения атрибутов мы используем свойство attributes и функцию getNamedItem(), а для чтения тела дескриптора — свойства f irstChild и data. Например:

garment.description=descrTag.firstChild.data;

С помощью этого выражения можно произвести разбор следующего XMLФрагмента:

172 Часть II. Основные подходы кразработке приложений

<description>Large tweedy hat looking like an unappealing strawberry </description>

Заметьте, что информация об изделиях автоматически помещается в глобальный массив по мере создания объектов; запись в массив предусмотрена в теле конструктора. Удалить изделие из массива также просто.

function unregisterGarment(id){ garments[id]«null;

}

Данный фрагмент кода удаляет из глобального массива, выполняющего функцию реестра, информацию об изделии, но не разрушает уже созданный экземпляр объекта Garment. Поэтому имеет смысл проверить, используется ли объект Garment.

Garment.prototype.isValid=function(){ return garments[this.id]!=null;

}

На текущий момент мы определили на стороне клиента простой способ обработки информации, передаваемой с сервера. На каждом шаге обработки используются объекты, простые для восприятия и поддержки. Повторим еще раз основные этапы разработки. Сначала мы генерируем на стороне сервера объектную модель. Исходной информацией являются данные из базы. В разделе 3.4.2 было рассмотрено решение этой задачи с помощью инструмента ORM (Object-Relational Mapping), который естественным образом обеспечивает двустороннее взаимодействие объектной модели и базы данных. Мы оформляем данные в виде объектов, модифицируем и сохраняем их.

Далее используем систему шаблонов для генерации потока XML-данных и выполняем разбор этого потока, чтобы создать объектную модель на уровне JavaScript-программы. На этом этапе мы выполняем разбор вручную. Возможно, вскоре появятся специализированные библиотеки, ориентированные на решение подобных задач.

Вприложении, предназначенном для администрирования, нам может понадобиться отредактировать данные, изменяя JavaScript-модель, а затем передать изменения серверу. При этом есть опасность появления двух копий модели, не синхронизированных друг с другом.

Вклассическом Web-приложении все "интеллектуальные" функции реализованы на сервере, следовательно, там расположена модель. Такое решение применяется независимо от используемого языка. В Aj ах-приложении мы распределяем обработку данных между клиентом и сервером, поэтому клиент получает возможность самостоятельно принимать некоторые решения, не обращаясь к серверу. Если клиент должен принимать только простые решения, мы можем написать код, ориентированный на конкретную задачу, но

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]