Вход/регистрация

31 июля 2013 г.

Клиентские шаблонизаторы

В нашей CMS давно используется серверный шаблонизатор для генерации HTML-страниц, отдаваемых клиенту. Концепция серверного шаблонизатора была разработана нами много лет назад и на сегодняшний день полностью удовлетворяет разработчиков. Поддерживается иерархия файлов шаблонов, возможность динамического переопределения, параметризации и разных других вкусностей.

Однако, в части клиентского шаблонизатора, долгое время были проблемы. Создавали свою реализацию обработки шаблонов, пробовали сторонние библиотеки, тестировали, выбирали…

И, наконец, выбрали!

Наиболее плотно мы работали с jQuery.Templates, Knockout и Underscore.

jQuery.Template был первым и использовался в нескольких крупных проектах. К сожалению, авторы этой библиотеки на неё «забили». Косячки и некоторые концептуальные недостатки вынудили нас искать другие решения.

Перебрав несколько популярных библиотек остановились на Knockout и Underscore.

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

Все было бы хорошо, если бы не ведро дёгтя в этой бочке вкусностей. То, что библиотека слегка притормаживает в сложных вложенных структурах на слабых машинах нас не сильно напрягало. Напрягли сложности динамической перестройки визуального представления при активной работе с AJAJ/AJAX. Если с сервера динамически передавались дополнительные шаблоны, содержащие скрипты, то иногда возникали проблемы, которые мы не могли решить.

С тоской поглядывали на jQuery.Templates, но возвращаться к нему не спешили.

Про Underscore слышали давно, но воспринимали эту библиотеку как набор полезных утилит. В документации среди большого описания утилит, которые нас мало интересовали, есть немного текста про шаблонизатор. На него внимание обратили совершенно случайно (не помню, кто навёл, но большое спасибо! ).

Через пару часов экспериментов был сделан вывод – вот оно счастье! Очень близкая нам по духу концепция шаблонизации. Всё чего хотелось, но не было в jQuery.Templates и Knockout тут работает!!!

Правда нет биндингов, но кому они нужны, если есть старые добрые events и jQuery.

Сравните два шаблона и сделайте выводы (модель не приводится ибо может быть одинакова для обоих библиотек):

Knockout

<table>
<tbody data-bind="visible:TmplAttrArray().length==0">
<tr><td colspan="4">Справочник пустой</td></tr>
</tbody>
<tbody data-bind="foreach: TmplAttrArray">
<tr data-bind="css: {'Item':AttrType>0, 'Head':AttrType==0}">
<td data-bind="text: $index()+1"></td>
<td>
<div data-bind="text: AttrName"></div>
<div data-bind="visible: DictionaryName! = ''">
<a href="#"
data-bind="attr: {'href': $root.codesUrl + '&CodeType=' + encodeURI(DictionaryName) }"
>Перейти к справочнику</a>
</div>
</td>
<td><div data-bind="text: AttrTypeName + ' (' + AttrType + ')'"></div></td>
<td>
<span data-bind="click:$parent.EditItem">Изменить</span>
<span data-bind="click:$parent.DeleteItem">Удалить</span>
</td>
</tr>
</tbody>
</table>

 

Underscore

<table>
<% if (TmplAttrArray.length) { %>
<tr class="Warning"><td colspan="4" >Справочник пустой</td></tr>
<% } else {
$.each(TmplAttrArray, function(i) { var o = this; %>
<tr class="<%= o.AttrType? 'Item': 'Head' %>">
<td><%= i %></td>
<td>
<div><%= o.AttrName %></div>
<% if (o.DictionaryName) { %>
<div>
<a href="<%= $root.codesUrl + '&CodeType=' + encodeURI(o.DictionaryName) %>"
>Перейти к справочнику</a>
</div>
<% } %>
</td>
<td><%= o.AttrTypeName + ' (' + o.AttrType + ') %></td>
<td>
<span onclick="EditItem(this)">Изменить</span>
<span onclick="DeleteItem(this)">Удалить</span>
</td>
</tr>
<% })
} %>
</table>

 

 

В рубрике: Новости    


Оцените: