Темплейты/шаблоны на JS (JavaScript template)

Хочу поделиться с вами одним хорошим решением для динамически генерируемых кусков html (и не только).

Конечно же об этом уже миллион и один раз написано, но если вдруг, по каким либо причинам, вы этого еще не видели или не слышали – то милости просим, вот пример (один из вариантов, мне больше всех остальных нравится): 

/* custom rendering template */
(function($){
	var cache = {};
	this.tmpl = function tmpl(str, data){
		// Figure out if we're getting a template, or if we need to
		// load the template - and be sure to cache the result.
		var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl($('#'+str).html()) :
			// Generate a reusable function that will serve as a template
			// generator (and which will be cached).
			new Function("obj",
				"var p=[],print=function(){p.push.apply(p,arguments);};" +
				// Introduce the data as local variables using with(){}
				"with(obj){p.push('" +
				// Convert the template into pure JavaScript
				str
					.replace(/[\r\t\n]/g, " ")
					.split("<\?").join("\t")
					.replace(/((^|\?>)[^\t]*)'/g, "$1\r")
					.replace(/\t=(.*?)\?>/g, "',$1,'")
					.split("\t").join("');")
					.split("\?>").join("p.push('")
					.split("\r").join("\\'")
				+ "');}return p.join('');"
			)
		;
		// Provide some basic currying to the user
		return data ? fn( data ) : fn;
	};
})(jQuery);

Как это работает? Да очень просто. Например у вас есть шаблон:


<?=name?> <?=price?> <?=description?> <? if ( colors.length ) { ?>
    <? for( var i = 0; i < colors.length; i++ ){ ?>
  • <?=colors[i]?>
  • <? } ?>
<? } ?>

В нем есть блоки, которые должны быть заменены на реальные данные ( <?=value?> ), более того, есть блоки, которые могут повторяться не один раз, так сказать итерироваться, для этого вам надо просто вызвать функцию (из выше приведенного примера):

jQuery('body').append(
	tmpl(jQuery('#template'), {
		"name": "Телек",
		"price": "$1000",
		"description": "Классный",
		"colors": [ "Зеленый", "Красный", "Черный" ]
	})
);

хочу только сказать, что конструкция вида <?= something ?> – вставляет данные, переданные в виде параметра в функцию, в указанное место. А вот эта конструкция <? something ?> – просто выполняется на JavaScript, как есть. Довольно таки универсальный подход, единственный момент – желательно не использовать комментарии в виде // в самом темплейте, хотя если немного доработать функцию то все возможно 🙂 .

Должен также заметить, что пример выполнен с использованием библиотеки jQuery, думаю не сложно будет отрефакторить так, чтобы можно было обойтись и без нее 🙂

Естественно, что эта функция была придумана не мной, а Джоном Ресигом, с небольшими изменениями (уже мной 🙂 ).