Использование вложенных шаблонов
Во время создания сложных приложений может быть полезно разделить общий шаблон на более мелкие секции и объединять нужные во время выполнения. Как вы увидите в дальнейших разделах этой главы, если использовать шаблоны таким образом, можно получить очень хороший и четкий результат. Мы начнем с основ, и в листинге 12-14 вы увидите, как можно обращаться из одного шаблона к другому.
Листинг 12-14: Вложенные шаблоны
<script type="text/javascript">
$(document).ready(function () {
$("<h2>Today's special offer: <span id=offer data-discount='0.50'>"
+ "50 cents off</span></h2>")
.insertAfter('h1')
.css({ color: "red", fontSize: "14pt", textAlign: "center" });
var data = [
{ name: "Astor", product: "astor", stocklevel: "10", price: 2.99 },
{ name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 },
{ name: "Rose", product: "rose", stocklevel: "2", price: 4.99 },
{ name: "Peony", product: "peony", stocklevel: "0", price: 1.50 },
{ name: "Primula", product: "primula", stocklevel: "1", price: 3.12 },
{ name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 },
];
var options = {
discount: $('#offer').data('discount'),
stockDisplay: function (product) {
return product.stocklevel > 0 ? 1 : 0;
}
}
var template = $('#flowerTmpl');
template.tmpl(data.slice(0, 3), options).appendTo("#row1");
template.tmpl(data.slice(3), options).appendTo("#row2");
});
</script>
<script id="flowerTmpl" type="text/x-jquery-tmpl">
<div class="dcell">
<img src="${product}.png" />
<label for="${product}">${name}:</label>
{{tmpl($data, $item) "#inputTmpl"}}
</div>
</script>
<script id="inputTmpl" type="text/x-jquery-tmpl">
<input name="${product}" data-price="${price - $item.discount}"
data-stock="${stocklevel}" value="${$item.stockDisplay($data)}" required />
</script>
В этом примере я разделил шаблон на два. Первый шаблон, flowerTmpl
, вызывается для каждой единицы (предмета) в массиве данных. Этот шаблон вызывает шаблон inputTmpl
, чтобы создать элемент ввода. Можно вызвать другой шаблон, используя тег {{tmpl}}
, например, вот так:
{{tmpl($data, $item) "#inputTmpl"}}
При использовании тега {{tmpl}}
есть три аргумента. Первые два – это единица данных, которую нужно обработать, и объект options
; и они размещены в круглых скобках, как вы видите. Третий аргумент – это шаблон, который нужно использовать. Он может быть выражен как селектор (как у меня) или доступен через переменную или функцию, определенную в скрипте.
Использование вложенных шаблонов для массивов
Если вы передали во вложенный массив единственное значение или объект, тогда указанный шаблон используется только один раз, как в предыдущем примере. Но если же вы передаете массив объектов, тогда шаблон используется для генерирования элементов для каждой единицы массива, как показано в листинге 12-15.
Листинг 2-15: Использование вложенного шаблона для массива
<script type="text/javascript">
$(document).ready(function () {
var data = [
{
rowid: "row1",
flowers:
[{ name: "Astor", product: "astor", stocklevel: "10", price: 2.99 },
{ name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 },
{ name: "Rose", product: "rose", stocklevel: "2", price: 4.99 }]
},
{
rowid: "row2",
flowers:
[{ name: "Peony", product: "peony", stocklevel: "0", price: 1.50 },
{ name: "Primula", product: "primula", stocklevel: "1", price: 3.12 },
{ name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 }]
}];
$('div.drow').remove();
$('#rowTmpl').tmpl(data).appendTo('div.dtable');
});
</script>
<script id="flowerTmpl" type="text/x-jquery-tmpl">
<div class="dcell">
<img src="${product}.png" />
<label for="${product}">${name}:</label>
<input name="${product}" data-price="${price}"
data-stock="${stocklevel}" value="${stocklevel}" required />
</div>
</script>
<script id="rowTmpl" type="text/x-jquery-tmpl">
<div id="${rowid}" class="drow">
{{tmpl($data.flowers) '#flowerTmpl'}}
</div>
</script>
Чтобы продемонстрировать эту возможность, я сделал рефакторинг объекта данных, таким образом, это сейчас массив, который содержит два объекта. Каждый из этих объектов определяет rowid
, который используется как идентификатор ряда, и массив из трех объектов, представляющих цветочную продукцию.
Я удалил из документа элементы div
для рядов, а затем использовал шаблон rowTmpl
, чтобы обработать данные. Этот шаблон генерирует замену для этих элементов div
для моей табличной CSS-верстки, а затем использует тег {{tmpl}}
, чтобы обработать массив с объектами для цветов, вот так:
<script id="rowTmpl" type="text/x-jquery-tmpl">
<div id="${rowid}" class="drow">
{{tmpl($data.flowers) '#flowerTmpl'}}
</div>
</script>
И хотя я вызвал шаблон только один раз, движок шаблона использует его, чтобы генерировать элементы для каждой единицы массива; это обозначает, что в конце для каждого цветка будет создан элемент в ячейке.
Вы можете вполне разумно возразить против структурирования данных, чтобы они отличались от намеченной верстки, поэтому в листинге 12-16 показано, как вы можете сделать так, чтобы оригинальный формат данных получил такой же результат (потому что довольно редко данные сразу же выражаются в идеальном формате для немедленного показа).
Листинг 12-16: Проведение рефакторинга встроенных данных для использования вложенных шаблонов
<script type="text/javascript">
$(document).ready(function () {
var originalData = [
{ name: "Astor", product: "astor", stocklevel: "10", price: 2.99 },
{ name: "Daffodil", product: "daffodil", stocklevel: "12", price: 1.99 },
{ name: "Rose", product: "rose", stocklevel: "2", price: 4.99 },
{ name: "Peony", product: "peony", stocklevel: "0", price: 1.50 },
{ name: "Primula", product: "primula", stocklevel: "1", price: 3.12 },
{ name: "Snowdrop", product: "snowdrop", stocklevel: "15", price: 0.99 },
];
var itemsPerRow = 4;
var slicedData = [];
for (var i = 0, j = 0; i < originalData.length; i += itemsPerRow, j++) {
slicedData.push({
rowid: "row" + j,
flowers: originalData.slice(i, i + itemsPerRow)
});
}
$('div.drow').remove();
$('#rowTmpl').tmpl(slicedData).appendTo('div.dtable');
});
</script>
<script id="flowerTmpl" type="text/x-jquery-tmpl">
<div class="dcell">
<img src="${product}.png" />
<label for="${product}">${name}:</label>
<input name="${product}" data-price="${price}"
data-stock="${stocklevel}" value="${stocklevel}" required />
</div>
</script>
<script id="rowTmpl" type="text/x-jquery-tmpl">
<div id="${rowid}" class="drow">
{{tmpl($data.flowers) '#flowerTmpl'}}
</div>
</script>
В этом примере я разместил элемент по рядам, я затем передал отформатированный объект данным методу tmpl
. Число единиц в каждом ряду определяется значением переменной itemsPerRow
, которое в этом примере я установил на 4
. Результат можно увидеть на рисунке 12-5.
Рисунок 12-5: Форматирование данных для шаблона

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