Библиотека ExtJS/Sencha

индекс
90,79

Архитектура клиентского приложения на ExtJS. Часть 1

ExtJS
Самое сложное в любой работе — это начать её. Итак, с чего же начать наше огромное клиентское приложение? В этой части я расскажу с чего начать и затрону три темы: Как организовать код, Что такое фасад, как его построить, что такое компоненты (и, конечно, как их начать писать).

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

Начало


Я бы предложил создать иерархию директорий в вашей папке с яваскриптами. Предположим, эта папка зовётся js. Тогда рекомендуемая мною иерархия директорий будет следующей:
  • ext
  • js
    • components
    • plugins
    • resources
    • ...

Папка ext содержит сам фреймворк, а js — файлы, внешние по отношению к фреймворку. В /js будет храниться единственный файл, который будет являться фасадом нашего приложения. В /js/components будут находиться все ваши наследники компонентов, о которых мы позже поговорим в деталях, в /js/plugins будут находиться плагины, т.е. компоненты, входящие в коллекцию plugins некоторых других компонентов. О плагинах я также расскажу немного позже. И, наконец, /js/resources в котором вы можете хранить файлы ресурсов со статическими переменными, различными вспомогательными функциями, переопределениями объектов и т.д. и пр.

Далее, на нашей страничке с приложением (скажем, index.html) организовываем в шапке наши скрипты таким образом:
  1. файлы /ext
  2. ресурсы из /js/resources
  3. плагины из /js/plugins
  4. модули-компоненты из /js/components
  5. фасад из /js

Почему именно в этом порядке? Потому, что такова наша иерархия зависимостей. Фреймворк от наших скриптов не зависит и от того стоит первым. Ресурсы могут зависеть лишь от объектов и функций из фреймворка, плагины используют ресурсы и фреймворк, модули-компоненты используют плагины, ресурсы и фреймворк, а фасад использует всё выше него. На то он и фасад.

Таким образом, мы решили проблему зависимости, которая у меня несколько раз вставала из-за неверного расположения компонентов.

Управление зависимостями в яваскрипте — вообще отдельная тема, но если вам интересно, советую обратить внимание на Jingo. Я с этой библиотекой познакомился совсем недавно и, как мне показалось, при её использовании слишком многое пришлось бы менять в существующем, уже отлаженом коде. Но проблему зависимостей эта библиотека решает весьма изящно.

Фасад



Дальше стоит написать каркас фасада. Что он из себя представляет? А представляет он из себя обычную функцию, которая в итоге монтируется к Ext.onReady (т.е. фасад начинает «жить» после того, как дом-модель нашей индексной странички будет построена). Вот пример фасада:

Copy Source | Copy HTML
  1. /**
      * filename:       facade.js
      * description:    Application Layout
      */
  2.  
  3. Ext.namespace("Layout");
  4. Layout.base = function(){
  5.     // Всплывающие подсказки необходимо инициализировать
  6.     Ext.QuickTips.init();
  7.  
  8.     // Далее мы определяем разные функции и объекты, которые будут
  9.     // использованы напрямую или косвенно во Viewport
  10.     // ...
  11.  
  12.     return {
  13.         init: function(){
  14.             new Ext.Viewport({/* конфигурация рабочей области, подключение модулей */});
  15.         }
  16.     };
  17. }();
  18. Ext.onReady(Layout.base.init, Layout.base);


Компоненты



Во Viewport, в фасаде мы подключили наши панели и навигацию. Теперь пора наладить базовое взаимодействие элементов меню с областью содержимого во Viewport. Предположим, вашей целью является смена содержимого по нажатию на элементы меню. У вас есть элемент «Отчёты» и элемент «Настройки» в вашем меню и вы хотите видеть в области содержимого, при нажатии на эти пункты меню, соответственно, содержимое, соответствующее отчётам и содержимое, соответствующее настройкам. Для этого вы в коллекцию items в панели, отвечающей за содержимое, помещаете компонент отчёта или компонент настроек (ситуация может немного варьироваться в зависимости от того, какой layout вы применили в области контента).

Итак. В данной статье я буду придерживаться соглашения о том, что компоненты — это наследники визуальных компонентов в Ext. Вам практически всегда необходимо будет иметь, как минимум, переопределённые стандартные визуальные компоненты. В различных туториалах по Ext такие компоненты называются preconfigured controls и представляют собой реализацию концепции наследования в ООП.

Вот так, если кратко, реализуются переопределения на примере GridPanel, выступающем в роли базового класса:
Copy Source | Copy HTML
  1. Ext.namespace("Application.Reports");
  2. Application.Reports.BaseReport = Ext.extend(Ext.grid.GridPanel, {
  3.       constructor: function(config){
  4.         // Нам очень редко придётся использовать сам конструктор, так что этот метод можно и вовсе
  5.         // опустить, если мы не хотим сделать что-то с конфигурацией ещё до того, как она попадёт
  6.         // в базовый конструктор. Но иметь представление о том, что функция конструктора всё же есть - надо.
  7.  
  8.         // Нельзя забывать вызывать базовый метод, если таковой имеется
  9.         Application.Reports.BaseReport.superclass.constructor.apply(this, arguments);
  10.     }
  11.     , initComponent: function(){
  12.         // А вот этот метод очень важен. Инициализация компонента вызывается после конструктора.
  13.         // А потому переопределённая конфигурация приоритетнее конфигурации, заданной пользователем
  14.         // в конструкторе. В нём мы и будем переопределять конфигурацию объекта.
  15.  
  16.         // Копируем с заменой все свойства второго аргумента в первый. Что бы там пользователь
  17.         // в конструкторе для свойств ни определил, если эти свойства будут во втором аргументе - они
  18.         // заменят собой свойства в нашем объекте
  19.         Ext.apply(this, {
  20.               title: "Our Title"
  21.             , loadMask: true
  22.             /* Остальные свойства */
  23.             , plugins: [
  24.                   // Пока не берите в голову, что такое Ext.ux.grid.MetaGrid.
  25.                   // RESOURCES.SETTINGS.RECORDS_PER_PAGE - это синглтон, определённый в файле ресурса, в /js/resources
  26.                   // RECORDS_PER_PAGE = значению 50.
  27.                   new Ext.ux.grid.MetaGrid({paging: {perPage: RESOURCES.SETTINGS.RECORDS_PER_PAGE}})
  28.             ]
  29.         });
  30.  
  31.         // Не забываем вызывать базовый метод инициализации
  32.         Application.Reports.BaseReport.superclass.initComponent.apply(this, arguments);
  33.     }
  34. });
  35.  


На этом я пока закончу. В следующей части:
  • Немного об архитектуре компонентов
  • Плагины
  • Советы
+24
19 ноября 2009, 23:08
97

комментарии (28)

+2
jcdenton_dx #
Спасибо, автор
+2
cleg #
сохраню ка я этот стартовый шаблончик… :)
+1
starodubcev #
Ждем продолжения
0
kirill533 #
Руководства на данную тему на сайте extjs.com (на английском):

http://www.extjs.com/learn/Manual:Component:Extending_Ext_Components
http://www.extjs.com/learn/Tutorial:Application_Layout_for_Beginners
http://www.extjs.com/learn/Tutorial:Writing_a_Big_Application_in_Ext

ну и весь список руководств:
www.extjs.com/learn/Tutorials

Думаю, начинающим будет легче понять английский вариант, чем эту статью на русском.
+2
oddy #
Я в заголовке написал о целевой аудитории. Эти люди уже должны были ознакомиться с предоставленными вами ссылками. Либо же у них были причины, по которым они не смогли с ними ознакомиться. Мой же цикл — не пересказ англоязычных статей, а попытка донести уникальный материал. Тот, которого пока ещё нигде нет. Думаю, вы сами сможете в этом убедиться во второй части статьи.
–1
kirill533 #
А для людей, которые уже ознакомились с данными статьями, Ваша статья еще менее полезна (для меня, например). Вы просто описываете свой подход к реализации и он не обязательно должен быть таким, как вы описали.
Единственное, что Вы задели тему зависимостей между компонентами. Проблема зависимостей достаточно острая в Extjs и нигде не раскрыта. Было бы интересно, если бы вы раскрыли свой взгляд на борьбу с зависимостями, а не писали как дать названия папкам, в которых будут файлы храниться.
0
oddy #
Как раз на борьбу с зависимостями первая статья и делает упор. Погодите делать выводы сейчас, пожалуйста. Возможно, вы поменяете своё мнение, когда увидите картину в целом (после окончания второй статьи).
0
kirill533 #
А еще я не согласен с Вашим употреблением термина «фасад».
В ООП он носит другой характер: Facade Pattern
0
kirill533 #
Хотя, возможно тут я Вас не так понял… Просто мало написано очень…
0
oddy #
Я сделаю более подробную вторую статью, но она не раскроет больше по тем топикам, по которым я прошёлся в первой. В этой статье фасадом является Layout.base, так как он достаточно точно следует определённому в вики термину. Но полемику по этому вопросу я здесь разводить не хотел бы.
+1
yelv #
Где же вы были раньше, я уже практически дописал админку для баннерной сети на ExtJS-е, компоненты, модули, плагины, довольно неплохо, если учесть, что знаком с ним всего пару недель :) Много, конечно, «костылей», но постепенно довожу код до ума.

Когда пишешь довольно большое приложение, возникает гора вопросов по поводу взаимодействия компонентов. Способы обращения к родительским и дочерним компонентам, использование параметров адресной строки для хранения открытой страницы (Ext.History) и много других вещей, после которых файловая структура отходит на задний план… Часто плюёшься от неочевидности некоторых решений, или наоборот, от уж излишне неадекватной реализации простых вещей.
+1
oddy #
Выбейте время на рефакторинг на проекте, если получится. Я себе уйму времени сэкономил в итоге, когда его закончил.
+1
oddy #
Внимание, в последнем блоке была допущена ошибка. Спасибо товарищу kirill533.
+1
muslimov #
текста хватило на два печенья и глоток кофе.
0
MaXyC #
согласен. сильно все сжато и в общих чертах. заходил с надеждой увидеть текст про архитектуру рич приложения
0
oddy #
К концу статьи мне бы хотелось, чтоб у читателя сложился каркас. Каркас — это вполне конкретная штука. Это то, с чего всё начинается. А детали реализации — это всего лишь детали.
+1
oddy #
Мне посоветовали не слать большую статью, а разбить её на небольшие, так как большие порции информации не всегда легко «глотаются». Видимо, это был хороший совет, раз вами кусок был проглочен за глоток кофе.
–1
muslimov #
огорчу вас, это совсем не комплимент с моей стороны, а с вашей стороны дешевый прием набора кармы.
+1
oddy #
Большое спасибо за ваши замечания. Они очень помогут мне написать очередную статью.
–1
Blurayman #
Я начинал изучать ExtJs не с туториалов, а с прочтения документации по API. Очень структурирует мозг перед началом проектирования и программирования клиентского приложения ;)
+2
oddy #
Простите, мне придётся с вами не согласиться. АПИ поможет реализовать, но не построить. В документации по апи нет ни слова о том, как начать писать приложение. Так что верным было бы всё же начать с туториалов.
0
Blurayman #
Я не говорил, что туториалы нужно совсем отбрасывать. API поможет понять, что может делать фреймворк, понять его архитектуру лучше. (Как мне видится, приложение с использованием фреймворка все-таки делается с оглядкой на его архитектуру).

На счет туториалов у меня все-таки скептическое мнение, т.к. нормальных туториалов, рассказывающих, как правильно строить client-side приложения (архитектура) со всеми прелестями (расширяемость, масштабируемость, модульность, i18n, быстродействие и.т.п.), крайне мало, если есть вообще. По большей части это тизеры (функционал, примеры) или проба пера разработчика.

Но я горячо поддерживаю обоими руками начинания автора топика сделать нормальных туториалов больше.
+1
AstralMan #
Спасибо, взял на заметку.
+1
jury #
Тоже сначала думал, что ExtJS хорошая библиотека для большого проекта: готовые виджеты, окна, плагины. Сначала всё вроде как ничего, но затем понадобилось писать свои дополнения или изменять существующие для своих нужд (в большом проекте без этого сложно обойтись). И началось. Пришло понимание того, что чтобы эффективно это делать надо быть просто гуру ExtJS + всё осложняется тем, что не все плагины стабильны.

Пришлось садится и думать что делать дальше, потому что с ExtJS тратилось просто неимоверное количество сил и времени на разработку. Выбор был за JQuery. Интегрировал и стало ясно: количество кода сократилось аж в 10 раз, множество поддерживаемых плагинов и фич, сама библиотка с дополнениями весит 180Кб против 610Кб у ExtJS. И скорость работы самой системы конечно очень сильно возросла. Легкость и простота понимания кода тоже рулят. В итоге сделал то же самое, но за время в 10 раз меньшее (и бесплатно)

Не сочтите за рекламу JQuery, просто есть негативный опыт работы с ExtJS и хотел поделиться с вами.
+1
kirill533 #
Да, учиться работать с Extjs — это то же самое, что научиться программировать на еще одном языке программирования. Но не нужно отпугивать людей.

Вы могли бы таки добить Extjs и стать Гуру.
–1
jury #
Я не хотел отпугивать. Правда. Для некоторых целей ExtJS подойдёт и каждый вправе сам решить что выбрать. Я просто хотел высказать свою точку зрения и рассказать про тот случай, который произошёл.

Если бы мне сказали про это раньше, то я бы не потерял несколько месяцев драгоценного времени.
0
Blurayman #
Здесь нужно отметить, что если уж вы беретесь делать приложение с использованием ExtJS, то клиентскую часть нужно делать полностью на нем. 512Кб Javascript-кода должны чем-то оправдываться )) Для простого сайта подойдут более легковесные аналоги типа JQueryUI и иже с ними.

Но, соглашусь с jury, олбучение ExtJS требует времени. Однако, если все получится, то у вас в руках инструмент, который эмулирует почти все распространенные элементы GUI в окне броузера.
0
Cancel #
У меня была ровно противоположная история. Мне надоело ковыряться с зоопарком разнородных jquery компонентов. Для каждого свои стили, а иногда эти стили ещё и конфликтуют между собой, разные названия методов в разных плагинах, которые делают по сути одно и то же. Короче, лучше уж досконально разобрать один цельный фреймворк, но один раз, чем постоянно «открывать» для себя разные плагины jQuery.

P.S.
Ext по сути гораздо больше, чем фреймворк, фактически это что-то вроде Qt в мире javascript.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.