Основы шаблонов
Шаблон - это текстовый файл, определяющий структуру, или внешний вид выходного файла, с предусмотренными позициями, в которые будут помещаться данные при отображении по шаблону (в Express шаблоны также называют представлениями).
Выбор шаблонов Express
В Express можно использовать много движков отображающих шаблонов ( template rendering engines). В этом руководстве для шаблонов будет использован Pug (ранее известный как Jade) . Это наиболее популярный в Node язык шаблонов, который о себе заявляет так: чистый, чувствительный к пробелам синтаксис для написания HTML, на который сильно повлиял Haml.
Разные языки шаблонов используют различные подходы для определения внешнего вида и разметки позиций для данных—некоторые используют HTML для определения внешнего вида, тогда как другие применяют различные форматы разметки, которые затем должны компилироваться в HTML. Pug - второго типа; он использует представление (representation) HTML, в котором первое слово в каждой строке обычно представляет элемент HTML, а отступы в следующих строках применяются, чтобы представить вложенные элементы. Результатом является определение страницы, которое транслируется непосредственно в HTML, и которое, вероятно, более краткое и легче читается.
Примечание: Недостаток применения Pug - это чувствительность к отступам и пробелам (если добавить лишний пробел в "плохом" месте, можно получить невразумительный код ошибки). Однако, если ваши шаблоны уже действуют, их очень легко читать и поддерживать.
Конфигурация шаблона
Когда создавался каркас (the skeleton website) веб-сайта LocalLibrary, он был настроен на использование Pug . Можно было заметить, что модуль pug включён в зависимости в файле package.json, и установлен (app.set(...)) как движок представлений в файле app.js. Эта установка показывает,, что движок представлений - pug, и что Express должен искать шаблоны в подкаталоге /views.
// View engine setup.
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
Если посмотреть содержимое каталога views, можно увидеть файлы с расширением .pug, в которых шаблоны представлений по умолчанию. Это представление для домашней страницы (index.pug) и базовый шаблон (layout.pug), который следует заменить нашим содержимым.
/express-locallibrary-tutorial //the project root /views error.pug index.pug layout.pug
Синтаксис шаблонов
Пример файла шаблона (ниже) демонстрирует многие наиболее полезные черты Pug.
Сначала отметим, что файл отражает структуру типового HTML-файла, причём первое слов в (почти) каждой строке является элементом HTML, а отступы используются, чтобы показать вложенные элементы. Так, например, элемент body
находится внутри элемента html
, а элементы p
(параграфы) - внутри элемента body,
и так далее. Невложенные элементы (т.е. индивидуальные параграфы) располагаются в отдельных строках.
doctype html
html(lang="en")
head
title= title
script(type='text/javascript').
body
h1= title
p This is a line with #[em some emphasis] and #[strong strong text] markup.
p This line has un-escaped data: !{'<em> is emphasised</em>'} and escaped data: #{'<em> is not emphasised</em>'}.
| This line follows on.
p= 'Evaluated and <em>escaped expression</em>:' + title
<!-- You can add HTML comments directly -->
// You can add single line JavaScript comments and they are generated to HTML comments
//- Introducing a single line JavaScript comment with "//-" ensures the comment isn't rendered to HTML
p A line with a link
a(href='/catalog/authors') Some link text
| and some extra text.
#container.col
if title
p A variable named "title" exists.
else
p A variable named "title" does not exist.
p.
Pug is a terse and simple template language with a
strong focus on performance and powerful features.
h2 Generate a list
ul
each val in [1, 2, 3, 4, 5]
li= val
Атрибуты элементов определены в скобках после соответствующих элементов. В скобках располагается список пар *имя атрибута=значение,*причём элементы списка разделяются запятой или пробелом. Например:
script(type='text/javascript')
,link(rel='stylesheet', href='/stylesheets/style.css')
meta(name='viewport' content='width=device-width initial-scale=1')
Значения всех атрибутов экранируются (т.е. такие символы как ">
" заменяются эквивалентными кодами HTML как ">"
) , чтобы предотвратить JavaScript инъекции и межсайтовые атаки.
Если после тэга стоит знак = , следующий текст рассматривается как выражение JavaScript. Например, ниже в первой строке, содержимое тэга h1
будет переменной title
(которая определена в файле или передана в шаблон из Express). Во второй строке содержимое параграфа - это текстовая строка, соединённая с переменной title
. В каждом из случаев поведение по умолчанию - экранировать строки.
h1= title
p= 'Evaluated and <em>escaped expression</em>:' + title
Если после тэга знак = отсутствует, тогда содержимое рассматривается как обычный текст. Внутри текста можно вставить экранированные или неэкранированные данные, применяя синтаксис #{}
и !{}
, как показано ниже. В простой текст можно также вставлять "сырой" HTML.
p This is a line with #[em some emphasis] and #[strong strong text] markup.
p This line has an un-escaped string: !{'<em> is emphasised</em>'}, an escaped string: #{'<em> is not emphasised</em>'}, and escaped variables: #{title}.
Примечание: Почти всегда желательно экранировать данные, полученные от пользователей (при помощи синтаксиса #{}
). Данные, которым можно верить (т.е. подсчитанное количество записей, могут быть выведены без экранирования значений.
Можно использовать символ конвейера ('|') в начале строки, чтобы отметить простой текст ("plain text"). Например, дополнительный текст, приведённый ниже, будет показан в той же строке, что и предыдущий, но не будет относиться к ссылке.
a(href='http://someurl/') Link text
| Plain text
Pug позволяет выполнять условные операции if
, else
, else if
и unless
— пример приведён ниже:
if title
p Переменная с именем "title" существует
else
p Переменной с именем "title" не существует
Можно также выполнять циклы (итерации), применяя синтаксис each-in
или while
. Фрагмент кода (ниже) содержит цикл по элементам массива, чтобы показать список элементов (отметим применение 'li=' для оценки "val" как переменной). Значение итератора val может быть также передано в шаблон как переменная!
ul
each val in [1, 2, 3, 4, 5]
li= val
Синтаксис разрешает также комментарии (которые попадут в результат или нет, по вашему желанию), смеси для создания повторно используемых блоков кода, операторы выбора case, и много другого. Более подробная информация - в документации The Pug docs.
Расширение шаблонов
Принято иметь общую структуру для всех страниц сайта, включая стандартную HTML-разметку для заголовка, футера, навигации и т.д. Вместо того, чтобы заставлять разработчиков дублировать эти образцы на каждой странице, Pug позволяет объявить базовой шаблон, а затем модифицировать его, заменяя только те небольшие части, которые различны на каждой конкретной странице.
Например, базовый шаблон layout.pug, созданный в каркасе проекта, имеет такой вид:
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
Тэг block
применён для отметки разделов контента, которые могут быть заменены в производных шаблона (если блок не переопределяется, будет использования его реализация в базовом классе).
Умолчание для index.pug (созданный для каркаса проекта) показывает, как можно заменить базовый шаблон. Тэг extends
идентифицирует базовый шаблон, который следует использовать, а затем мы используем block section_name,
чтобы отметить новый контент раздела, который мы заменяем.
extends layout
block content
h1= title
p Welcome to #{title}
Next steps
- Return to Express Tutorial Part 5: Displaying library data.
- Proceed to the next subarticle of part 5: The LocalLibrary base template.