Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 08.04.2013, 17:23
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Шаблонизатор 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 или привязка данных.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности

Последний раз редактировалось FINoM, 08.04.2013 в 17:42.
Ответить с цитированием
  #2 (permalink)  
Старый 08.04.2013, 21:07
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

1) Вопрос скорости трансляции не принципиален, т.к. любой нормальный шаблонизатор поддерживает предварительную трансляцию в js (т.е. на этапе сборки проекта в отдельный файлик) и во всех крупных проектах используется именно такой подход.
2) Имхо далеко не самый удачный синтаксис.
3) Отсутствие системы повторного использование кода.

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

Ну а так за велосипед респект
__________________
kobezzza
code monkey
Ответить с цитированием
  #3 (permalink)  
Старый 08.04.2013, 23:51
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от kobezzza
далеко не самый удачный синтаксис.
Это JS, всякие синтаксические велосипеды довольно часто вызывают кучу проблем.
Сообщение от kobezzza
Отсутствие системы повторного использование кода.
Например?
Сообщение от kobezzza
для маленьких и средних проектов сойдёт, для больших и тем более огромных - увы
Ну тогда не знаю. Пожалуй, я работаю только над маленькими и средними проектами.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #4 (permalink)  
Старый 09.04.2013, 08:45
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Сообщение от FINoM Посмотреть сообщение
Это JS, всякие синтаксические велосипеды довольно часто вызывают кучу проблем.
Да норм всё. А вот кучи проблем с твои синтаксисом я могу назвать:

1) Захотим мы переписать шаблонизатор к примеру на пхп, чтобы использовать на сервере, а потом обнаружим, что в шаблоне используются очень специфичные JS конструкции и огребём гемора. Шаблонизатор не должен уметь много - это скорее недостаток, чем плюс.

2) Пришёл новый верстальщик в проект: он не знает JS и ему трудно вкурить твой синтаксис.

3) Когда размер шаблона начинает превышать n количество строк то код превращается в месиво, особенно с таким синтаксисом.

4) Лучше просто, чем сложно.

Сообщение от FINoM Посмотреть сообщение
Например?
Вот есть у тебя шаблон А и есть B. И так вышло, что тело шаблона B включает в себя тело A, что делать: первое что приходит в голову, это вызвать шаблон в шаблоне, но такое решение слишком прямое (и порождает дополнительные связи), т.к. в реальной жизни нам часто нужно не просто включить тело шаблона, но и передекларировать часть его структуры и в твоём случае это закончится копипастой, а была бы поддержка наследования шаблонов, то данная проблема решилась элегантно и просто.

Пример, как это можно сделать:
https://github.com/kobezzza/Snakeskin#--3
http://habrahabr.ru/post/168093/

Сообщение от FINoM Посмотреть сообщение
Ну тогда не знаю. Пожалуй, я работаю только над маленькими и средними проектами.
К сожалению всё приходит с опытом.
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 09.04.2013 в 08:51.
Ответить с цитированием
  #5 (permalink)  
Старый 09.04.2013, 22:45
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от kobezzza
Захотим мы переписать шаблонизатор к примеру на пхп, чтобы использовать на сервере, а потом обнаружим, что в шаблоне используются очень специфичные JS конструкции и огребём гемора.
Как вариант, вместо шаблонизатора, можно переписать шаблоны (не более сложная задача). Да и юзайте node.js
Сообщение от kobezzza
Шаблонизатор не должен уметь много - это скорее недостаток, чем плюс.
Очень спорно. Люди успешно юзают EJS и не парятся.
Сообщение от kobezzza
Пришёл новый верстальщик в проект: он не знает JS и ему трудно вкурить твой синтаксис.
А вкурить синтаксис другого шаблонизатора проще?
Сообщение от kobezzza
Когда размер шаблона начинает превышать n количество строк то код превращается в месиво, особенно с таким синтаксисом.
Тоже спорно. Шаблоны, как правило, используют всего лишь each и иногда методы (.toFixed и пр.). В таком случае, шаблон на том же jQuery.tmpl будет ненамного отличаться от моего.
Сообщение от kobezzza
Лучше просто, чем сложно.
Полностью согласен
Сообщение от kobezzza
Вот есть у тебя шаблон А и есть B. И так вышло, что тело шаблона B включает в себя тело A
В таком случае, я просто компилирую родительский шаблон, потом вставляю скомпилированные дочерние блоки. В моих проектах всегда есть метод .render (как и в тех, которые написаны на том же backbone), так что нужно просто определить в JS, как рендерить блок.

Ну и да, по поводу синтаксиса: твой синтаксис довольно сложен для верстальщика (имхо, конечно же), но в случае с тем же EJS, изучение синтаксиса, то есть обычного JS, ему будет только на пользу.
Сообщение от kobezzza
К сожалению всё приходит с опытом.
Это был сарказм.

Ты, конечно, прав, но вопрос не только в опыте, но и в том, какие задачи ты решаешь. Это очень хорошо, что ты решаешь определенную задачу, а не пишешь сферического коня (я надеюсь). Но, появись иная задача, и в твоём шаблонизаторе найдется какая-нибудь проблема, которая не решаема внутренними методами.

Лично мне никогда не приходилось перетаскивать шаблоны на сервер. Поэтому, твоё замечание об этом я расцениваю, как вполне реальную, но редкую задачу, с которой я, возможно, никогда не встречусь, не зависимо от стажа и опыта.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #6 (permalink)  
Старый 09.04.2013, 23:25
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от FINoM
Лично мне никогда не приходилось перетаскивать шаблоны на сервер.
Сообщение от FINoM
как вполне реальную, но редкую задачу
займешься высоко нагруженными проектами, столкнешься с переносом на сервер. В таких проектах обычно идет пре-компиляция шаблонов, на уровне выкладки, пред подготовка перед запуском.
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #7 (permalink)  
Старый 10.04.2013, 00:07
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от devote
займешься высоко нагруженными проектами, столкнешься с переносом на сервер. В таких проектах обычно идет пре-компиляция шаблонов, на уровне выкладки, пред подготовка перед запуском.
У меня пока что был только перенос логики. Спорить не буду, может эта задача и не редкая.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #8 (permalink)  
Старый 10.04.2013, 12:09
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

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

Сообщение от kobezzza
Лучше просто, чем сложно
"лучше меньше, да лучше" )


Не скажу, что знаток шаблонизаторов, но кое-что сказать могу. Я пользуюсь http://aefxx.com/api/jqote2-reference/ Не то чтобы супер-гуд, но тем не менее.

1. Хеширование шаблонов как лямбда функций
2. Удобный синтаксис вызова
3. В большинстве случае нет нужды в
Сообщение от FINoM
<%#each( this, user )%>
    <div data-abind="<%= at.bindData( user ) %>"><%= name %></div>
<%#/each%>
подобных конструкциях, т.к. шаблонизатор сам итерирует, достаточно только передать массив. Пример (т.е. массив будет развернут автоматически, этого более чем достаточно):
<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. Наследования шаблонов нет (вроде как)
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #9 (permalink)  
Старый 14.04.2013, 19:21
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от nerv_
Хеширование шаблонов как лямбда функций
Объясни, пожалуйста, что такое хеширование шаблонов (и зачем оно нужно) и что в данном контексте значит "лямбда функция". Если я всё правильно понял, ты немного опечатался (не хеширование, а кеширование), и эту задачу решает карринг, который наличествует в шаблонизаторе Резига и сохранён в моём.
Сообщение от nerv_
Текущий объект итерации доступен как this.
ХЗ, не вижу в этом смысла, имея переменную _item (которую можно переопределить). Вызывать call/apply не хочется.
Сообщение от nerv_
подобных конструкциях, т.к. шаблонизатор сам итерирует, достаточно только передать массив
Ну не знаю... Почему тогда не итерировать объект.
__________________
"Matreshka is fucking awesome" © чувак с Reddit
Matreshka.js - Три возможности
Ответить с цитированием
  #10 (permalink)  
Старый 15.04.2013, 21:59
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от FINoM
ты немного опечатался (не хеширование, а кеширование)
да. Я набирал текст в хроме, он выделил слово красным и предложил исправить. Я исправил, результат ты видишь

Сообщение от FINoM
Ну не знаю... Почему тогда не итерировать объект.
может и итерирует, я не проверял. Массив - интуитивно.

Сообщение от FINoM
не вижу в этом смысла
this пишется проще и глазу приятнее )

Сообщение от FINoM
и что в данном контексте значит "лямбда функция"
насколько я понял, этим термином автор плагина называет функцию, полученную в результате работы шаблонизатора (та, кот. генерит разметку)
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нативный шаблонизатор Антон Крамолов AJAX и COMET 191 28.12.2012 17:47
JS шаблонизатор Andrei jQuery 9 07.11.2011 16:46
Extjs + шаблонизатор + фреймворк Sea ExtJS 1 24.09.2010 15:52