Разрабатывая сайты мне всегда хотелось облегчить себе жизнь, так я познакомился с jQuery. Все было бы хорошо если бы проекты не погружались в зыбучую смесь UI и js кода. Следующим этапом стало то что мы выделили UI Шаблоны в отдельные файлы, код стал более чистым, но, черт побери, все равно приходилось писать кучу UI кода, например вставка и настройка дополнительных компонентов в шаблон, event bind, надписи и т.д. И только после всего этого на выходе получался нужный нам компонент. Возникало, конечно, много проблем, особенно когда дизайнер менял шаблон, но все это решаемо.
Мне всегда хотелось что бы дизайнеры рисовали мир, а програмисты оживляли его. И желательно что бы эти миры практически не пересекались и давали свободу и тем и другим. И так перейдем к сути.
jsMVC состоит из трех вещей:
![](https://habrastorage.org/r/w780q1/getpro/habr/post_images/6a9/112/ace/6a9112acec2491a5d81eb431655d5949.jpg)
— слайд 3 —
Компонент состоит из Шаблона+CSS, js«класса» + декларативное описание.
js«class» определяется в пространстве имен jsMVC.Components. и имеет примерно такой вид:
Мне всегда хотелось что бы дизайнеры рисовали мир, а програмисты оживляли его. И желательно что бы эти миры практически не пересекались и давали свободу и тем и другим. И так перейдем к сути.
jsMVC состоит из трех вещей:
- Компонент
- Шаблон 2.0
- Компиляция
Компонент
![](https://habrastorage.org/getpro/habr/post_images/6a9/112/ace/6a9112acec2491a5d81eb431655d5949.jpg)
— слайд 3 —
Компонент состоит из Шаблона+CSS, js«класса» + декларативное описание.
js«class» определяется в пространстве имен jsMVC.Components. и имеет примерно такой вид:
jsMVC.Components.Button = {
Init: function(){// Вызывается после добавления объкта в дом
jsMVC.Components.Component.Init.call(this);//Базовый метод...
//<Действия>
},
SetEnable: function(flag){...}, // Определяем геттер и сеттер для свойства Enable
GetEnable:function() {...}
//<Опеделедяем еще кучу методов...>
}
* This source code was highlighted with Source Code Highlighter.
Желательно методы начинать с большой буквы, ниже будет понятно почему.
Далее декларируем свойства и события:
![](https://habrastorage.org/r/w780q1/getpro/habr/post_images/420/623/c48/420623c489421df07121474020a87cea.jpg)
— слайд 5 —
jsMVC.CreateCompileInfoByObject(
{
Name: 'Button',
Properties: {
Enable: {
Type: 'Boolean',
Access: 'GETSET'
},
Text: {}
},
Events: {
onClick: {}
}
});
* This source code was highlighted with Source Code Highlighter.
Указание типа и доступа свойств является не обязательным.
Декларирование нужно для компиляции и редактора.
Шаблон
Шаблоны состоят из HTML тегов, других компонентов, казаний событий, установки свойств.
Для примера Expander
jsMVC.Templates.Expander =
'<div>'+
'<div name="content"/>'+
'<div class="expander-control">'+
'<component name="bToggle" type="Button" class="cExpander-cButton-bToggle">'+
'<properties>'+
'<key name="Text" value="*"></key>'+//Установка свойства Text
'</properties>'+
'<events>'+
'<key name="onClick" value="Toggle"/>'+//Биндим событие
'</events>'+
'</component>'+
'</div>'+
'</div>';
* This source code was highlighted with Source Code Highlighter.
Можно сделать и такое
jsMVC.Templates.TestComponent = '<div>'+
'<component type="Expander">'+
'<content>'+ //по умолчанию into="content", Вы помните что в Expander есть тег с именем "content"?
'<div> Test TEXT </div>'+
'<component type="Button">'+
'<properties>'+
'<key name="Text">Click Me</key>'+//Установка свойства Text
'</properties>'+
'<events>'+
'<key name="onClick" value="Clear"/>'+//Биндим событие
'</events>'+
'</component>'+
'</content>'+
'<content into="bToggle">'+// Добавим чтонибудь в клавишу
'<div> Test 2 </div>'+
'</content>'+
'</component>'+
'</div>';
* This source code was highlighted with Source Code Highlighter.
Компиляция
При первом создании объекта происходит компиляция Шаблона и Js«класса» в js функцию которая создает объект. При этом с помощью декларации компонента проверяются названия свойств, события и т.д.
![](https://habrastorage.org/r/w780q1/getpro/habr/post_images/a73/ab4/cdb/a73ab4cdbc064203a4312b8ad3805b42.jpg)
— слайд 7 —
Вызвав эту функцию, на выходе мы получаем jQuery объект, который содержит:
- все методы js«класса»
- объект Components в который будут помещены jQuery обьекты (теги, компоненты) отмеченые атрибутом «name»
- объект Events который будет содержать все забинденые события
Далее поместив объект в DOM страницы необходимо вызвать метод Init(), по умолчанию этот метод вызовет метод Init() у всех вложеных компонентов.
Производительность
Так что насчет производительности? Для тестов был взят простой объект:
<div class="menu“>
<div class="menu-background"/>
<span name="text" class="menu-text"/>
</div>
* This source code was highlighted with Source Code Highlighter.
Суть теста в том что бы создать 1000 — у объектов, установить в span.menu-text текст «ТЕСТ».
Тест проводился на FF3.0.3, AMD 64x2 4800+, 2.51ГГц, 2Gb RAM, WinXP SP2
![](https://habrastorage.org/r/w780q1/getpro/habr/post_images/e79/f8c/940/e79f8c94026f9858e9c9fe15938bf591.jpg)
![](https://habrastorage.org/r/w780q1/getpro/habr/post_images/008/244/6ae/0082446ae9813ee71db645db0972924e.jpg)
— слайд 9 —
jsMVC,SetText() — получил высокую производительность, так как метод SetText устанавливает текст через innerHTML.
DOM,innerHTML — создание всех элементов через createElement и т.д.,
jQuery + innerHtml — создание основного элемента и заполнение его через innerHTML, результат практически совпадает с полным созданием шаблона через jQuery
Полная статистика:
Time:700 ms Name: "jQuery", $(Template), $(TAG.class[@atr="..."]), $().text()
Time:591 ms Name: "jQuery", $(Template), $(.class), $().text()
Time:441 ms Name: "jQuery", $(Template), $(obj[0].childNodes[]), $().text()
Time:463 ms Name: "jQuery", $()[0].innerHtml, $(obj[0].childNodes[]), $().text()
Time:680 ms Name: "jQuery", $()[0].innerHtml, $(TAG.class[@atr="..."]), $().text()
Time:565 ms Name: "jQuery", $()[0].innerHtml, $(.class), $().text()
Time:383 ms Name: "jQuery", $()[0].innerHtml, $(.class), obj[0].innerHTML
Time:471 ms Name: "jQuery", $()[0].innerHtml, $(#id), obj[0].innerHTML
Time:484 ms Name: "DOM", createElement(), $(TAG.class[@atr="..."]), $().text()
Time:391 ms Name: "DOM", createElement(), $(.class), $().text()
Time:297 ms Name: "DOM", createElement()+innerHtml, $(obj.childNodes[]), $().text()
Time:261 ms Name: "DOM", createElement(), $(DOMElement), $().text()
Time:357 ms Name: "DOM", createElement(), $(DOMElement), $().html()
Time:101 ms Name: "DOM", createElement(), $(DOMElement), innerHTML
Time:113 ms Name: "DOM", createElement(), $(DOMElement), innerHTML, cache element
Time:303 ms Name: "jsMVC", $().text()
Time:129 ms Name: "jsMVC", SetText() — spec object method
Итог
- Каждый компонент может содержать множество дочерних компонентов.
- Сокращение времени разработки
- Производительность близка к ручному созданию дом (с оговорками)
- Дизайнеры создают мир, программисты оживляют его.
Проект распространяется под GPLv3
Буду рад критике, багам, идеям и предложениям.
Текущая версия 1.0alpha, есть еще недоделки и баги.
В конце недели будет выпущен конструктор компонентов WYSIWYG (готов на 80%), полностью написаный на jsMVC.
Исходники.
П.С.: я думаю есть куча похожих идей, хочу лишь предложить одну из реализаций.
П.С.2: С анг. языком у меня проблемы, был бы очень рад если бы кто нибудь помог мне перевести эту заметку, если она заинтересует людей.