Underscore.js templates

Backbone.js тесно интегрирован с библиотекой Underscore.js, которая предоставляет мощный механизм для шаблонизации данных. Основной инструмент — функция _.template, позволяющая отделять логику приложения от представления и создавать динамические HTML-шаблоны.


Основы работы с _.template

Функция _.template принимает строку-шаблон и возвращает функцию, которая, при вызове с объектом данных, возвращает готовый HTML. Синтаксис шаблонов строится на трёх основных конструкциях:

  • <%= expression %> — вставка значения выражения с экранированием HTML.
  • <%- expression %> — вставка значения выражения без экранирования (опасно, если данные получены извне).
  • <% code %> — выполнение произвольного JavaScript-кода, например, условных операторов или циклов.

Пример базового шаблона:

var templateString = "<h1><%= title %></h1><p><%= description %></p>";
var template = _.template(templateString);

var html = template({ title: "Backbone.js", description: "Фреймворк для структуры JS-приложений" });
console.log(html);
// Вывод: <h1>Backbone.js</h1><p>Фреймворк для структуры JS-приложений</p>

Встраивание логики в шаблоны

Шаблоны поддерживают выполнение JavaScript-кода внутри блоков <% %>. Это позволяет управлять выводом на основе условий или циклов.

Пример использования условий и циклов:

var templateString = `
<ul>
  <% items.forEach(function(item) { %>
    <% if (item.active) { %>
      <li class="active"><%= item.name %></li>
    <% } else { %>
      <li><%= item.name %></li>
    <% } %>
  <% }); %>
</ul>
`;

var template = _.template(templateString);

var html = template({
  items: [
    { name: "Item 1", active: true },
    { name: "Item 2", active: false },
    { name: "Item 3", active: true }
  ]
});

console.log(html);

Интерполяция и экранирование

По умолчанию <%= %> экранирует специальные символы HTML (<, >, &, "), предотвращая XSS-уязвимости. Если требуется выводить HTML-код, можно использовать <%- %>:

var templateString = "<div><%- htmlContent %></div>";
var template = _.template(templateString);

var html = template({ htmlContent: "<strong>Важно!</strong>" });
console.log(html);
// Вывод: <div><strong>Важно!</strong></div>

Это особенно полезно при работе с безопасным HTML-контентом, загруженным с сервера.


Компиляция и кеширование шаблонов

Для оптимизации производительности шаблоны можно компилировать заранее и сохранять в переменных или объектах. Это позволяет многократно использовать один и тот же шаблон без повторной компиляции.

var templates = {};

templates.item = _.template("<li><%= name %></li>");

var html = templates.item({ name: "Item A" });
console.log(html); // <li>Item A</li>

Интеграция с Backbone.View

Backbone.js активно использует шаблоны для отрисовки представлений. Обычно создаётся метод render в Backbone.View, который применяет шаблон к данным модели или коллекции:

var ItemView = Backbone.View.extend({
  tagName: 'li',
  template: _.template("<%= name %>"),

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  }
});

var item = new Backbone.Model({ name: "Пример элемента" });
var view = new ItemView({ model: item });
console.log(view.render().el.outerHTML); // <li>Пример элемента</li>

При работе с коллекциями обычно используется итерация по модели и создание дочерних представлений для каждого элемента.


Настройка разделителей шаблонов

Underscore.js позволяет изменять стандартные разделители шаблонов с <% %> на кастомные, если необходимо избегать конфликтов с другими языками разметки.

_.templateSettings = {
  evaluate: /\{\{([\s\S]+?)\}\}/g,
  interpolate: /\{\{=([\s\S]+?)\}\}/g,
  escape: /\{\{-([\s\S]+?)\}\}/g
};

var templateString = "{{= name }}";
var template = _.template(templateString);
console.log(template({ name: "Кастомный синтаксис" })); // Кастомный синтаксис

Это особенно полезно при интеграции с серверными шаблонами, где стандартные <% %> уже используются.


Динамическая отрисовка и производительность

При использовании Backbone.js и Underscore.js важно помнить:

  • Избегать частой пересборки шаблонов на каждый рендер. Лучше компилировать один раз и применять многократно.
  • Для больших коллекций использовать буферизацию HTML, а не множественные прямые вставки в DOM.
  • Сохранять чистоту шаблонов, отделяя логику обработки данных от представления.

Практические рекомендации

  • Шаблоны должны содержать минимальную логику, ограничиваясь условными конструкциями и циклами.
  • Все вычисления лучше делать в модели или коллекции, передавая в шаблон готовые данные.
  • Экранование данных по умолчанию помогает предотвратить XSS, использовать <%- %> только при доверенном контенте.
  • Компиляция шаблонов при инициализации приложения повышает производительность и упрощает поддержку кода.

Underscore.js templates обеспечивают гибкий и безопасный способ динамического формирования интерфейса в приложениях на Backbone.js, позволяя отделить структуру HTML от бизнес-логики и упрощая поддержку масштабных проектов.