Шаблонизатор aTemplate
Сегодня расскажу о шаблонизаторе, который я сделал несколько месяцев назад, но немного завис с документацией. Шаблонизатор успешно используется в нескольких проектах и работает на ура, перетерпевая только самые незначительные изменения. В качестве объяснения процитирую текст из первой версии документации, где я противопоставлял jQuery.tmpl и EJS со своим (этот текст будет выпилен, так как во-первых не очень красиво получается, во-вторых есть куча альтернатив).
--------- Шаблонизатор aTemplate — модификация микро-шаблонизатора Джона Резига http://ejohn.org/blog/javascript-micro-templating/ с расширенным функционалом. Целью aTemplate является создание шаблонизатора, лишенного минусов самых популярных на сегоднышний день шаблонизаторов jQuery.tmpl и EJS. Что умеет aTemplate? 1. Делать всё, что оригинальный шаблонизатор Джона Резига. Синтаксис шаблонов аналогичен шаблонизатору EJS. Как известно, jQuery.tmpl имеет собственный синтаксис шаблонов, далекий от оригинального JS кода, поэтому его скорость меньше. Кроме этого, у людей, использующих jQuery.tmpl часто возникают трудности из-за этого: сделать что-либо, выходящее за рамки шаблонизатора, например, получить индекс текущей итерации либо невозможно, либо очень сложно. aTemplate, как и EJS лишен этого минуса, так как в нем используется самый обычный Javascript без заморочек создателя. 2. Перебирать элементы с помощью each, который наличествует в jQuery.tmlp, но отсутствует в EJS. Часто разработчику приходится перебирать набор данных из массива или объекта, и, в случае с EJS, приходится использовать некрасивый for: <% for( var i = 0; i < users.length; i++ ) { %> <span><%= users[ i ].name %></span> <%} %> или <% for( var i in users ) if( users.hasOwnProperty( i ) ) { %> <span><%= users[ i ].name %></span> <%} %> или <% for( var i = 0; i < users.length; i++ ) with( users[ i ] ){ %> <span><%= name %></span> <%} %> Вместо {{each users}} <span>${name}</span> {{/each}} Второй вариант удобнее, правда? aTemplate делает это так (хотя синтаксис EJS тоже сработает): <%#each( users )%> <span><%= name %></span> <%#/each%> Причем, поддерживаются как массивы, так и обычные объекты. 3. Привязывать данные к элементу. Часто есть нужда привязать данные к элементу, генерируемому шаблонизатором. Такого функционала нет ни в jQuery.tmpl ни в EJS. 4. Работа в качестве jQuery плагина. Не пугайтесь, aTemplate можно использовать и без этой библиотеки. Что не умеет aTemplate Делать ajax запросы для получения шаблонов. Автору такой функционал показался излишеством. При желании программист, использующий aTemplate, может добавить его самостоятельно. В итоге мы получаем: 1. Скорость, сравнимую с шаблонизатором Джона Резига 2. Гибкость, как в EJS 3. Удобство, как jQuery.tmpl -------- Конструкция <%#each%> может содержать псевдоаргументы: перебираемый объект, текущий элемент итерации, ключ. <%#each( users, user, index )%> ... <%#/each%> По умолчанию эти псевдоаргументы следующие: this, _item, _key Это значит, что можно не определять все три. Написав: <%#each%> ... <%#/each%> Получаем то же самое, что и: <%#each( this, _item, _key )%> ... <%#/each%> Шаблонизатор запускается так: aTemplate({ template: 'templatetext', data: data }); Поддержка карринга сохранена: aTemplate({ template: 'templatetext' })( data ); Вместо template можно указать name: aTemplate({ name: 'name' }) При этом, template будет браться из элемента (div, script...) с атрибутом data-atemplate. Я предпочитаю использовать script: <script type="text/atemplate" data-atemplate="mytemplate">...</script> По поводу работы в качестве jQuery плагина: $( '#mytemplateblock' ).aTemplate( data ); или $( '#mytemplateblock' ).aTemplate()( data ); Где '#mytemplateblock' - блок, в котором находится шаблон, например: <div id="mytemplateblock">...</div> Я всегда испытывал проблемы с тем, как же привязать объект к ноде в текстовом шаблоне. Привязка данных — это очень простая фича, которой мне всегда не хватало. Раньше приходилось извращаться вот так: <% for( var i = 0; i < this.length; i++ ) { %> <div data-name="<%= this[i].name %>" data-email="<%= this[i].email %>" data-age="<%= this[i].age %>" ... ><%= this[i].name %></div> <%}%> Здесь это делается так: <%#each( this, user )%> <div data-abind="<%= at.bindData( user ) %>"><%= name %></div> <%#/each%> Вытащить данные из элемента можно так: aTemplate.getBindedData( node ); или по айдишнику, который генерируется функцией at.bindData: aTemplate.getBindedData( id ); Людям, использующим jQuery будет особенно удобно извлекать данные: $( element ).data( 'aTemplate' ); или так: $( element ).data().aTemplate; или вот так: $( element ).aTemplateData(); Несмотря на краткость кода, о функционале можно писать очень много, поэтому я могу забыть что-то упомянуть. Ах, да, для тех, кто использует EJS и его небольшое дополнение view.js, последний был портирован для aTemplate: <script type="text/atemplate"> link_to( name, href ); </script> (честно признаюсь, тестирование всех функций view.js не проводилось) https://github.com/finom/aTemplate В репозитории только код. В документации расчитываю показать все возможные применения (пока не могу сказать, когда это случится). Несмотря на это, шаблонизатор уже можно юзать. Код очень простой (я надеюсь), поэтому, легко разобраться, как работает тот же each или привязка данных. |
1) Вопрос скорости трансляции не принципиален, т.к. любой нормальный шаблонизатор поддерживает предварительную трансляцию в js (т.е. на этапе сборки проекта в отдельный файлик) и во всех крупных проектах используется именно такой подход.
2) Имхо далеко не самый удачный синтаксис. 3) Отсутствие системы повторного использование кода. Резюме: для маленьких и средних проектов сойдёт, для больших и тем более огромных - увы, такие шаблоны превращаются в месиво: поддерживать конечно можно, но это жесть. Ну а так за велосипед респект :) |
Цитата:
Цитата:
Цитата:
|
Цитата:
1) Захотим мы переписать шаблонизатор к примеру на пхп, чтобы использовать на сервере, а потом обнаружим, что в шаблоне используются очень специфичные JS конструкции и огребём гемора. Шаблонизатор не должен уметь много - это скорее недостаток, чем плюс. 2) Пришёл новый верстальщик в проект: он не знает JS и ему трудно вкурить твой синтаксис. 3) Когда размер шаблона начинает превышать n количество строк то код превращается в месиво, особенно с таким синтаксисом. 4) Лучше просто, чем сложно. Цитата:
Пример, как это можно сделать: https://github.com/kobezzza/Snakeskin#--3 http://habrahabr.ru/post/168093/ Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Ну и да, по поводу синтаксиса: твой синтаксис довольно сложен для верстальщика (имхо, конечно же), но в случае с тем же EJS, изучение синтаксиса, то есть обычного JS, ему будет только на пользу. Цитата:
Ты, конечно, прав, но вопрос не только в опыте, но и в том, какие задачи ты решаешь. Это очень хорошо, что ты решаешь определенную задачу, а не пишешь сферического коня (я надеюсь). Но, появись иная задача, и в твоём шаблонизаторе найдется какая-нибудь проблема, которая не решаема внутренними методами. Лично мне никогда не приходилось перетаскивать шаблоны на сервер. Поэтому, твоё замечание об этом я расцениваю, как вполне реальную, но редкую задачу, с которой я, возможно, никогда не встречусь, не зависимо от стажа и опыта. |
Цитата:
Цитата:
|
Цитата:
|
Цитата:
Цитата:
Не скажу, что знаток шаблонизаторов, но кое-что сказать могу. Я пользуюсь http://aefxx.com/api/jqote2-reference/ Не то чтобы супер-гуд, но тем не менее. 1. Хеширование шаблонов как лямбда функций 2. Удобный синтаксис вызова 3. В большинстве случае нет нужды в Цитата:
<script type="text/x-jqote-template" id="template-timeline-ruler"> <div class="timeline-ruler-pick" style="width:<%=this.width%>px;"> <%=this.value%> </div> </script> 4. Текущий объект итерации доступен как this. 5. Наследования шаблонов нет (вроде как) |
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 15:18. |