Задача: в JS на основе имеющихся данных сгенерить блок (кусок хтмл), заполнить его этими данными и вставить в DOM.
Например, нам нужно создать простой блок с превьюшкой и подписью. Для него мы каким-то образом получили вот такие данные:
var data = {
url: '/test/',
thumb_src: 'test.gif',
thumb_width: 60,
thumb_height: 30,
caption: 'Трам-парам!'
};
В итоге для этих данных хотим получить вот такой хтмл:
<div class="preview"><p class="image"><a href="/test/"><img src="test.gif" width="60" height="30"/></a></p><p class="caption">Трам-парам!</p></div>
Встают вопросы: в каком виде хранить шаблон и как впердолить в этот шаблон наши данные?
Вручную создавать элементы (createElement) и аппендить их (appendChild) довольно муторно. Получается громоздко и шаблон размазывается тонким слоем по JS-коду.
Часто делают конкатенацию кусочков шаблона вперемешку с данными:
var result = '<div class="preview"><p class="image"><a href="' + data.url + '"><img src="' + data.thumb_src + '" width="' + data.thumb_width + '" height="' + data.thumb_height + '"/></a></p><p class="caption">' + data.caption + '</p></div>';
Тоже не ахти — постоянно путаешься в этом нагромождении одинарных и двойных кавычек, к тому же хочется все-таки иметь шаблон в чистом виде.
Я использую способ, который подсмотрел в лекциях Дугласа Крокфорда. Добавляем в прототипы объекта String
метод supplant
, который в строке ищет выражения заключенные в фигурные скобки {}. Каждое найденное выражение используется как ключ к переданному объекту, и, если по этому ключу лежит строковое или числовое значение, то выражение в фигурных скобках заменяется этим значением.
/**
* supplant() does variable substitution on the string. It scans
* through the string looking for expressions enclosed in {} braces.
* If an expression is found, use it as a key on the object,
* and if the key has a string value or number value, it is
* substituted for the bracket expression and it repeats.
*/
String.prototype.supplant = function(o) {
return this.replace(/{([^{}]*)}/g,
function(a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
Теперь мы можем сделать так:
var template = '<div class="preview"><p class="image"><a href="{url}"><img src="{thumb_src}" width="{thumb_width}" height="{thumb_height}"/></a></p><p class="caption">{caption}</p></div>';
var result = template.supplant(data);
Еще один пример (подстановка данных в сообщение пользователю):
var template = 'Take train {number} from {from} to {to}.';
var data = {
from: 'Madrid',
to: 'Barcelona',
number: '78A'
};
var result = template.supplant(data);