В статье, где мы впервые рассмотрели Handlebars (шаблонизатор JavaScript), был работающий пример, но возможно он был недостаточно убедителен в отношении, почему использование Handlebars лучше конкатенации для создания HTML сниппетов.
Затем был еще этот пример с Ajax запросом, возвращающим JSON данные. Там мы также использовали простой JavaScript, но там было уже совсем неприятно. Давайте теперь посмотрим, как мы можем делать те же самые вещи, используя Handlebars.
В предыдущем примере мы получили JSON-ответ со следующим содержимым:
{
"title" : "Code Maven",
"description" : "Coding is fun!",
"articles" : [
{
"title" : "Handling user events in JavaScript",
"url" : "http://code-maven.com/handling-events-in-javascript"
},
{
"title" : "On-load counter with JavaScript and local storage",
"url" : "http://code-maven.com/on-load-counter-with-javascript-and-local-storage"
}
]
}
Мы использовали этот код:
function ajax_get(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log('responseText:' + xmlhttp.responseText);
try {
var data = JSON.parse(xmlhttp.responseText);
} catch(err) {
console.log(err.message + " in " + xmlhttp.responseText);
return;
}
callback(data);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
ajax_get('/try/examples/js/data.json', function(data) {
document.getElementById("title").innerHTML = data["title"];
var html = "<h2>" + data["title"] + "</h2>";
html += "<h3>" + data["description"] + "</h3>";
html += "<ul>";
for (var i=0; i < data["articles"].length; i++) {
html += '<li><a href="' + data["articles"][i]["url"] + '">' + data["articles"][i]["title"] + "</a></li>";
}
html += "</ul>";
document.getElementById("text").innerHTML = html;
});
Используя Handlebars
Функция ajax_get
осталась такой же. Она была рассмотрена в статье про Ajax запрос.
Изменения в строках 23-25, где вместо конкатенации HTML по фрагментам, мы получаем шаблон из элемента с id text-template
,
компилируем исходный код шаблона в функцию template
, а затем просто передаем в нее данные, которые мы получили
из Ajax запроса. Намного чище, чем раньше, когда мы должны были думать об использовании одинарных кавычек снаружи так,
чтобы они не пересекались с двойными кавычками, которые мы хотели использовать для HTML атрибутов.
examples/js/ajax_handlebars.js
function ajax_get(url, callback) {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log('responseText:' + xmlhttp.responseText);
try {
var data = JSON.parse(xmlhttp.responseText);
} catch(err) {
console.log(err.message + " in " + xmlhttp.responseText);
return;
}
callback(data);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
ajax_get('/try/examples/js/data.json', function(data) {
document.getElementById("title").innerHTML = data["title"];
var source = document.getElementById('text-template').innerHTML;
var template = Handlebars.compile(source);
var html = template(data);
document.getElementById("text").innerHTML = html;
});
Сам шаблон находится в HTML файле в теге script
.
examples/js/ajax_handlebars.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.min.js"></script>
<script id="text-template" type="text/x-handlebars-template">
<h2>{{title}}</h2>
<h3>{{description}}</h3>
<ul>
{{#each articles}}
<li><a href="{{url}}">{{title}}</a></li>
{{/each}}
</ul>
</script>
<h1 id="title"></h1>
<hr>
<div id="text"></div>
<script src="ajax_handlebars.js"></script>
Плейсхолдеры для {{title}}
и {{description}}
это простые значения, которые мы уже видели во
введении в Handlebars,
но здесь также есть цикл для прохождения по элементам массива.
{{#each articles}}
начинает цикл по элементам массива, лежащего в ключе articles
.
Цикл заканчивается, когда мы достигаем инструкции {{/each}}
.
Внутри цикла мы можем использовать ключи объектов, которые являются элементами массива articles
.
Это делает шаблон гораздо чише, чем он был раньше, когда мы использовали конкатенацию.