Трудности перевода.
В русском языке слово "шаблон" устоялось в качестве перевода двух английских терминов - pattern и template.
Первое понятие относится к области программной архитектуры и означает некоторые идеи или концепции, которые можно выделить во множестве программных проектов вне зависимости от языка программирования. Наиболее корректный перевод слова pattern - повторяющийся мотив (или рисунок), подобно рисунку плитки или обоев. Принятый в IT-среде перевод - шаблоны проектирования (или даже "калька" - "паттерны" проектирования).
Второе понятие (о котором и пойдёт речь в данной заметке) связано с вёрсткой веб-страниц. Шаблоном (или веб-шаблоном) называют текстовую строку (или даже файл), содержащую как обычную последовательность html-тегов, выводимую без изменений, так и специальные символы и ссылки, которые некоторая процедура заменяет на конкретные значения. Более подходящим названием для этого программного элемента был бы термин "бланк". Подобно своему бумажному прототипу веб-шаблон состоит из неизменных, заранее отпечатанных в типографии элементов, часто утвержденных некоторым стандартом и пустых клеток, ячеек или полос, которые заполняются от руки или на печатной машинке. Такие клетки и ячейки часто содержат подсказки мелким шрифтом - Ф.И.О. (фамилия-имя-отчество) или М.П. (место печати).
Немного истории.
Первые "шаблоны", которые "бланки" появились в языке КОБОЛ, ставшем стандартом в бизнес-среде. Зарплатные ведомости или различные отчеты представляют собой те самые бланки, которые содержат стандартные элементы и конкретные данные в виде фамилий и сумм. Древние языки программирования не имели такой роскоши как конкатенация строк, поэтому вывод данных, содержащих постоянные и переменные данные был довольно громоздким. Типичная функция вывода на экран могла выводить только один параметр - строку или переменную, а иногда для вывода разных типов данных требовались разные функции. Нужно было следить за всеми пробелами и переводами строк, выравниваниями, вывод разрывался в самом неподходящем месте.
Возникла идея выводить только одну строку текста, в которой та часть, где должны находиться переменные, будет содержать специальные символы, а функция автоматически будет менять эти символы на нужные значения. Существующая во множестве языков функция printf типичный пример такого шаблонизатора. Пусть нам нужно вывести строку:
Name: John Surname: Smith Country: USA Salary: $30000
где имя, фамилия, страна проживания и зарплата находятся в соответствующих переменных. Вместо набора команд:
prints("Name: "); prints(name);
prints(" Surname: "); prints(surname);
prints(" Country: "); prints(country);
prints(" Salary: $"); printn(salary);
println();
можно использовать такую конструкцию:
printf("Name: %s Surname: %s Country: %s Salary: $%d\n",
name, surname, country, salary);
Первый параметр функции printf и является таким бланком-шаблоном. Значения переменных, которые передаются в функцию как остальные параметры, заменяют специальные символы %s (строковая переменная) и %d (числовая переменная).
Для работы с шаблонами в Underscore и lodash используется функция _.template и переменная _.templateSettings.
_.template(templateString, [settings]) // underscore
_.template(templateString, [data], [settings]) // lodash
Функция template является генератором функций на основании строки шаблона (templateString). Это строка может содержать три типа тегов, содержимое которых преобразуется при выводе (все остальные части строки выводятся без изменений):
<% %> - вычисление (evaluate), RE: /<%([\s\S]+?)%>/g
<%= %> - замена (interpolate), RE: /<%=([\s\S]+?)%>/g
<%- %> - эскапирование (escape), RE: /<%-([\s\S]+?)%>/g
Содержимое тега "вычисление" - обычный JavaScript-код. Шаблонизатор заменяет код на результат его вычисления.
Содержимое тега "замена" - ключи некоторого объекта (который передается в качестве параметра сгенерированной функции). В итоговой строке ключи объекта заменяются на значения.
Тег "эскапирование" ведёт себя аналогично тегу "замена" с HTML-эскапирование результатов.
Результат выполнения _.template() - функция, которая может получать объект с данными, заполнять шаблон этими данными и возвращать текстовую строку (это может быть строка таблицы или элемент списка HTML-документа).
var tmpl = "Hello, <%= name %>!";
var data = { name: "John" };
var ftmpl = _.template(tmpl);
console.log(ftmpl(data)); // > Hello, John!
В случае lodash объект для заполнения шаблона можно передать в качестве параметра не сгенерированной функции а сразу функции template.
_.template(templateString, [data], [settings]) // lodash
Функция template является генератором функций на основании строки шаблона (templateString). Это строка может содержать три типа тегов, содержимое которых преобразуется при выводе (все остальные части строки выводятся без изменений):
<% %> - вычисление (evaluate), RE: /<%([\s\S]+?)%>/g
<%= %> - замена (interpolate), RE: /<%=([\s\S]+?)%>/g
<%- %> - эскапирование (escape), RE: /<%-([\s\S]+?)%>/g
Содержимое тега "вычисление" - обычный JavaScript-код. Шаблонизатор заменяет код на результат его вычисления.
Содержимое тега "замена" - ключи некоторого объекта (который передается в качестве параметра сгенерированной функции). В итоговой строке ключи объекта заменяются на значения.
Тег "эскапирование" ведёт себя аналогично тегу "замена" с HTML-эскапирование результатов.
Результат выполнения _.template() - функция, которая может получать объект с данными, заполнять шаблон этими данными и возвращать текстовую строку (это может быть строка таблицы или элемент списка HTML-документа).
var tmpl = "Hello, <%= name %>!";
var data = { name: "John" };
var ftmpl = _.template(tmpl);
console.log(ftmpl(data)); // > Hello, John!
В случае lodash объект для заполнения шаблона можно передать в качестве параметра не сгенерированной функции а сразу функции template.
console.log(_.template(tmpl, data)); // Только lodash
Или же учитывая тот факт, что template возвращает функции, можно вызвать ее немедленно в обеих билиотеках:
console.log(_.template(tmpl)(data)); // lodash и underscore
Параметры шаблонов хранятся в объекте _.templateSettings, но могут перекрываться параметрами из опционального объекта settings.
Переменная _.templateSettings является объектов с ключами interpolate, evaluate, escape, содержащими соответствующие регулярные выражения для указания форматов тегов, используемых в шаблоне. Для того, чтобы использовать теги в стиле Mustache можно использовать следующие регулярные выражения:
_.templateSettings.evaluate = /\{\{([\s\S]+?\}\}/g;
_.templateSettings.interpolate = /\{\{=([\s\S]+?\}\}/g;
_.templateSettings.escape = /\{\{-([\s\S]+?\}\}/g;
По умолчанию шаблон может "заполняться" объектом с любым именем, лишь бы этот объект имел поля с ключами, совпадающими с теми, которые используются в шаблоне. Для этого внутри генерируемой функции используется крайне медленный оператор with. Если поместить в строку шаблона тег интерполяции в виде ключ.значение и указать имя объекта из которого шаблон будет брать значения, в параметре settings:
_.template("Hello, <%= data.name %>", { variable: data })(data);
вместо
_.template("Hello, <%= name %>")(data);
заполнение шаблона будет происходить гораздо быстрее (до 10 раз). Однако при использовании шаблона теперь всегда нужно будет использовать временную переменную с именем, которое "прописано" в шаблоне.
Или же учитывая тот факт, что template возвращает функции, можно вызвать ее немедленно в обеих билиотеках:
console.log(_.template(tmpl)(data)); // lodash и underscore
Параметры шаблонов хранятся в объекте _.templateSettings, но могут перекрываться параметрами из опционального объекта settings.
Переменная _.templateSettings является объектов с ключами interpolate, evaluate, escape, содержащими соответствующие регулярные выражения для указания форматов тегов, используемых в шаблоне. Для того, чтобы использовать теги в стиле Mustache можно использовать следующие регулярные выражения:
_.templateSettings.evaluate = /\{\{([\s\S]+?\}\}/g;
_.templateSettings.interpolate = /\{\{=([\s\S]+?\}\}/g;
_.templateSettings.escape = /\{\{-([\s\S]+?\}\}/g;
По умолчанию шаблон может "заполняться" объектом с любым именем, лишь бы этот объект имел поля с ключами, совпадающими с теми, которые используются в шаблоне. Для этого внутри генерируемой функции используется крайне медленный оператор with. Если поместить в строку шаблона тег интерполяции в виде ключ.значение и указать имя объекта из которого шаблон будет брать значения, в параметре settings:
_.template("Hello, <%= data.name %>", { variable: data })(data);
вместо
_.template("Hello, <%= name %>")(data);
заполнение шаблона будет происходить гораздо быстрее (до 10 раз). Однако при использовании шаблона теперь всегда нужно будет использовать временную переменную с именем, которое "прописано" в шаблоне.
Комментариев нет :
Отправить комментарий