Русские документы
Ежедневные компьютерные новости RSS rusdoc.ru  Найти :
Новости
Последние поступления
Книжный магазин
  Hardware:
Видеоустройства
Системные платы
Процессоры
Мобильные устройства
Аудиосистема
Охлаждение системы
Накопители информации
КПК и ноутбуки
Телефоны и связь
Периферия
Система
Сети
Разные устройства
 
  Programming:
Web-разработка
Языки программирования
Технологии и теория
Разработка игр
Программная инженерия
 
  Software:
Операционные системы
Windows 7
Базы данных
Обзоры программ
Графика и дизайн
   
  Life:
Компьютерная жизнь
Разные материалы
   
Партнеры
Публикация
Правовая информация
Реклама на сайте
Обратная связь
Экспорт в RSS Экспорт в RSS2.0
    Читать в Яндекс.Ленте



Создание сложных приложений в ExtJS

Раздел: Programming / Ajax @ 29.05.2008 | Ключевые слова: extjs framework ajax версия для печати

Источник: habrahabr

Предисловие

Я решил написать эту статью для тех пользователей Ext 2.x, которые уже переросли одну единственную HTML-страницу со встроенными скриптом, создающим простое окно или форму, для тех, которые уже решили, что Ext — это их путь и для тех, которые превозмогая трудности связанные с большими объемами кода, понимают, что нуждаются в его структурировании.

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

Замечу, что описываемый подход является работоспособным, четко структурированным, без труда поддерживаемым и, одним словом: рабочим!

Что значит сложное приложение?

Когда вы оперируете объектом Viewport с BorderLayout, grid-таблицей и формой в одном файле, это, конечно же, не сложное приложение, правда? Если же у вас десятки окон, в каждом из которых grid-таблицы, формы или BorderLayout и все это добро раскидано по десяткам файлов, то это уже сложное и большое приложение, верно?

В немецком языке имеется одно милое словечко: Jein = Ja + Nein

Ответом на оба приведенных утверждения будет Jein. Вопрос заключается в следующем: когда приложение становится большим и сложным? Ответ прост: в тот самый момент как вы начинаете его таковым ощущать. Это момент когда становится сложно ориентироваться в большом количестве файлов или начинаются проблемы при поиске определенного места в случае попытки понять отношение компонентов, например, и так далее.

Можно с уверенностью говорить, что каждое приложение сложно столь же насколько простое достойно быть хорошо написанным и может стать по-настоящему большим, как только мы начнем добавлять новый функционал, наращивать объем кода, добавлять правила CSS и т.д. Лучшей и самой безопасной установкой при создании нового приложения является — «Я начинаю сложное приложение!»

Файлы и директории

То, что необходимо организовать в первую очередь. В нашем распоряжении всегда имеется каталог DocumentRoot так что все подкаталоги, затронутые ниже, будут приводиться относительно него.

Рекомендуемая структура каталогов:

  • ./css (опциональная link)
  • ./ext (ссылка)
  • ./img (ссылка)
  • ./js
  • index.html

Слово «ссылка» означает, что каталог является мягкой ссылкой на реальный каталог, где лежат файлы. Преимущество этого приема в том, что, например, вы можете загрузить новую версию Ext в любой реальный каталог и заставить ссылку указывать на него, что избавит от редактирования путей в вашем коде. Можно проводить тестирование новой версии и если все в порядке, оставить ссылку указывать на новую версию, а если нет, то просто вернуть ее назад.

  • css — хранилище всех ваших стилей. Если у вас имеются глобальные стили, вроде цветов компании или оформления шрифтов, то вы также можете создать этот каталог как ссылку;
  • ext — ссылка на используемую вами версию Ext, как это было описано ранее;
  • img — каталог с вашими изображениями. Также может содержать подкаталоги для иконок и т.п.;
  • js — будет содержать все JavaScript файлы приложения, а также их скомпонованную версию;
  • index.html — HTML-файл являющийся входной точкой вашего приложения. Вы можете назвать его как угодно, да и быть html-файлов может несколько, например, для операции аутентификации. Но в любом случае файл входной точки (с обработчиком onReady) должен быть один;
  • дополнительно вы можете создать директорию или ссылку на серверную часть приложения (./classes в моем случае). Можно дать ей какое угодно имя, но следует выбрать согласующееся со всеми приложениями, которые вы разрабатываете (имена ./server, ./php будут неплохими вариантами).

index.html

Минимальное содержимое index.html может быть следующим:

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <link rel="stylesheet" type="text/css" href="./ext/resources/css/ext-all.css">

  <link rel="stylesheet" type="text/css" href="./css/application.css">

  <script type="text/javascript" src="./ext/adapter/ext/ext-base.js"></script>

  <script type="text/javascript" src="./ext/ext-all-debug.js"></script>

  <script type="text/javascript" src="./application.js"></script>

  <title>A Big Application</title>

</head>

<body></body>

</html>

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

js/application.js

Нам понадобится файл, где мы сможем поместить onReady обработчик. Пусть его имя будет application.js. Минимальное содержимое такого файла приведено ниже:

// vim: sw=4:ts=4:nu:nospell:fdc=4

/**

 * An Application

 *

 * @author    Ing. Jozef Sakalos

 * @copyright (c) 2008, by Ing. Jozef Sakalos

 * @date      2. April 2008

 * @version   $Id$

 *

 * @license application.js is licensed under the terms of the Open Source

 * LGPL 3.0 license. Commercial use is permitted to the extent that the

 * code/component(s) do NOT become part of another Open Source or Commercially

 * licensed development library or toolkit without explicit permission.

 *

 * License details: http://www.gnu.org/licenses/lgpl.html

 */



/*global Ext, Application */



Ext.BLANK_IMAGE_URL = `./ext/resources/images/default/s.gif`;

Ext.ns(`Application`);



// application main entry point

Ext.onReady(function() {



    Ext.QuickTips.init();



    // code here



}); // eo function onReady



// eof

Ваши код может иным, но обязательным шагом будет установка Ext.BLANK_IMAGE_URL в значение, ссылающееся на ваш сервер. Это путь к прозрачному 1х1 изображению, которое используется Ext в качестве плэйсхолдера и если он ведет в пустоту, вы можете столкнуться с различными проблемами отрисовки такими как: отсутствие изображения стрелки в Ext.form.ComboBox, иконок и т.п. Возможно, что вам также понадобится создать глобальную переменную для вашего приложения (в данном случае это Application).

В чем вы должны быть уверенны, так это в том, что onReady обработчик наличествует у вас лишь однажды — в точке входа в приложение.

css/application.css

Поместите в этот файл все свои стили, если они у вас есть. В случае если вам необходимо лишь малое число таковых, то, возможно, не имеет смысла создавать для них отдельный файл. Можно записать их непосредственно в документ, используя <style>.

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

Как делать не надо

Что обычно следует за тем как был получен некий базис, такой, какой имеется у нас на данном этапе? Начинаем писать код. Итак, мы погрузились в кресло и начали творить:

var vp = new Ext.Viewport({

     layout:`border`

    ,items:[

        new Ext.grid.GridPanel({

            store:new Ext.data.Store({

                 proxy:new Ext.data.HttpProxy({ ...

Одну минуточку. Развивая подобное, мы очень скоро будем иметь все 10000 строк кода в application.js, а это последнее что нам необходимо. Очевидно, был пропущен какой-то этап. Если мы создали такой огромный файл, почему бы нам не вставить его код непосредственно в index.html?

Правильный путь: разделяй и властвуй

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

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

Преднастроенные классы

Ну вот, как только вы покончили с анализом и определением составных частей своего приложения можно приступить к написанию одного из них. Как лучше всего это сделать? Наилучшим решением будет написание классов расширяющих стандартные компоненты Ext, ввиду того, что последние уже имеют все настройки, перезаписываемые переданными в их конструкторы значениями. Я называю такие расширения преднастроенными классами т.к. они редко вносят новый функционал и служат в основном для конфигурирования. Примером может служить grid-таблица «Персонал» со своею моделью колонок, хранилищем, настройками сортировки, редакторами и т.д.

В таком случае конфигурация нашего окна могла бы выглядеть следующим образом:

var win = new Ext.Window({

     title:`Personnel`

    ,widht:600

    ,height:400

    ,items:{xtype:`personnelgrid`}

});

win.show();

Написание преднастроенного класса

Разберемся на примере:

Application.PersonnelGrid = Ext.extend(Ext.grid.GridPanel, {

     border:false

    ,initComponent:function() {

        Ext.apply(this, {

             store:new Ext.data.Store({...})

            ,columns:[{...}, {...}]

            ,plugins:[...]

            ,viewConfig:{forceFit:true}

            ,tbar:[...]

            ,bbar:[...]

        });



        Application.PersonnelGrid.superclass.initComponent.apply(this, arguments);

    } // eo function initComponent



    ,onRender:function() {

        this.store.load();



        Application.PersonnelGrid.superclass.onRender.apply(this, arguments);

    } // eo function onRender

});

Ext.reg(`personnelgrid`, Application.PersonnelGrid);

Что у нас тут происходит? Мы расширяем Ext.grid.GridPanel, создавая новый класс-расширение Application.PersonnelGrid и регистрируем для него новый xtype с именем personnelgrid.

По сути, мы передаем обычной grid-таблице все настройки достаточные для превращения ее в специализированную grid-таблицу «Персонала». Начиная с этого момента, у нас имеется новый компонент, строительный блок нашего приложения, который мы можем использовать где угодно (в окне, на панели, самостоятельно) для отображения списка сотрудников. Создать его можно следующим образом:

var pg = new Application.PersonnelGrid();

или используя xtype (т.н. ленивое создание):

var win = new Ext.Window({

     items:{xtype:`personnelgrid`}

    ,....

});

Организация и хранение преднастроенных классов

Код приведенный выше не нуждается, да и не будет запускаться в обработчике onReady — он не оперирует DOM, а просто создает JavaScript объект. Следовательно, он может и должен быть помещен в отдельный файл (js/Application.PersonnelGrid.js) и будет включаться в хедер index.html.

Что ж, пока все идет хорошо — у нас почти все готово и все (почти), что нам нужно так это продолжать описывать преднастроенный классы, класть их в ./js, включать в index.html и собирать наше приложение из их экземпляров как кусочки головоломки.

Выглядит неплохо, а?

Межкомпонентное сообщение

Представьте себе, что вам необходимо рамочный макет (border layout) со списком ссылок слева (west region) и панелью закладок посередине (center region). Щелчок по ссылке должен создавать новую закладку в центре. Где вы поместите логику всего происходящего, обработчик события и код создания? Слева или в центре?

Нигде. Почему? Если у нас есть преднастроенный класс, который создает и отображает список слева, а мы помещаем логику туда, то его существование теряет смысл без центрального региона. Мы просто не сможем использовать список без панели закладок.

Если же мы поместим логику в центральную область, итог будет схожим: панель закладок не может существовать без списка ссылок.

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

Производственная система

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

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

Производственная система будет подключать:

  • ext-all.js
  • app-all.js
  • application.js

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

Заключение

В общем-то это все… Существуют специализированные техники для некоторых классов Ext, много иных серверных и клиентских фишек, но то, что было изложено выше — общая концепция.

Счастливого кодинга!

На правах переводчика:

  • Статья зацепила меня тем, что описывает общую концепцию работы со сложным приложением в конкретном случае разработки в ExtJS;
  • далее перевод планируется поместить в официальный мануал проекта рядом с оригиналом, поэтому просьба реагировать не только плюсами и минусами, но и в текстовом виде, пожалуйста;
  • кажушийся странным танец вокруг ссылок при описании файловой организации обусловлен тем, что сами разработчики ExtJS интенсивно используют построение собранных из множества файлов билдов. В таком случае новая версия того же ExtJS это как все исходное дерево, так и билд фреймворка. Гораздо удобнее, конечно, изменить ссылку, чем копировать туда-сюда много файлов.

Это интересно:








версия для печатиРаспечатать статью


Вернуться в раздел: Programming / Ajax


Реклама:
Читать наc на:

Add to Google
Читать в Яндекс.Ленте






Rambler's Top100
© Copyright 1998-2012 Александр Томов. All rights reserved.