Экспресс в действии (7): представления и шаблоны: Pug и EJS

Node.js JavaScript Express

2017-08-23-cover.jpg
2017-08-23-cover.jpg

Большая часть предыдущего контента посвящена самой инфраструктуре Express, включая: введение в Express, принцип работы и функции фреймворка. В конце серии мы обратим внимание на цепочку инструментов для среды Express. Узнайте, как использовать эти инструменты для расширения функциональности платформы Express.

Во-первых, в этой статье мы обсудим использование механизмов шаблонов представлений. С помощью этих механизмов шаблонов мы можем динамически генерировать HTML-контент. Ранее мы использовали EJS и внедряли контент с использованием синтаксиса переменных. Но это только верхушка айсберга всей части шаблонизатора. Далее вы узнаете о различных методах вставки контента, EJS, Pug и других функциях шаблонизатора.

Функции экспресс-просмотра

Прежде чем мы начнем, необходимо объяснить, что такое движок просмотра? Механизм представления как термин программирования в основном означает «модуль, который выполняет визуализацию представления». Двумя наиболее часто используемыми механизмами просмотра в среде Express являются Pug и EJS. Следует отметить, что раннее имя Пага было Джейд, и его по какой-то причине пришлось переименовать.

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

Простой пример рендеринга вида

Давайте рассмотрим процесс рендеринга EJS на простом примере:

var express = require("express");
var path = require("path");
var app = express();

app.set("view engine", "ejs");

app.set("views", path.resolve(__dirname, "views"));

app.get("/", function(req, res) {
    res.render("index");
});

app.listen(3000);

Перед запуском кода нужно пройтиnpm installУстановите EJS и Express. Если вы посетите домашнюю страницу приложения после установки, программа будет искатьviews/index.ejsфайл и визуализировать его с помощью EJS. Кроме того, в проекте обычно используется только один движок просмотра, потому что несколько движков могут внести в проект ненужную сложность.

сложная визуализация вида

Давайте рассмотрим более сложный пример, где используются оба движка представления Pug и EJS:

var express = require("express");
var path = require("path");
var ejs = require("ejs");
var app = express();
app.locals.appName = "Song Lyrics";
app.set("view engine", "jade");
app.set("views", path.resolve(__dirname, "views"));
app.engine("html", ejs.renderFile);
app.use(function(req, res, next) {
    res.locals.userAgent = req.headers["user-agent"];
    next();
});
app.get("/about", function(req, res) {
    res.render("about", {
        currentUser: "india-arie123"
    });
});
app.get("/contact", function(req, res) {
    res.render("contact.ejs");
});
app.use(function(req, res) {
    res.status(404);
    res.render("404.html", {
        urlAttempted: req.url
    });
});
app.listen(3000);

Хотя код выглядит сложным, шаги после декомпозиции на самом деле довольно просты. Далее мы вызываем вышеуказанноеrenderПроанализируйте код по адресу:

  1. Экспресс каждый раз, когда вы звонитеrenderОбъект контекста создается каждый раз и передается в механизм представления при рендеринге. Фактически, эти объекты контекста являются переменными, которые будут использоваться в представлении.

    Express сначала сделает все запросы общедоступнымиapp.localдобавляются свойства, которые уже существуют в представлении. затем добавьтеres.localsсвойства в и могут быть связаны сapp.localКонфликтующие свойства переопределяются. Наконец, добавьтеrenderСвойства на месте вызова и, возможно, операции переопределения. Например, посетите/aboutКогда используется путь, объект контекста содержит три свойства:appname,userAgent,currentUser;доступ/contactпуть, свойства объекта контекста толькоappname,userAgent; и свойства объекта контекста становятся:appname,userAgent,urlAttempted.

  2. Далее мы установим, следует ли включать кэширование представлений. На самом деле кеш представления не кеширует представление, на самом деле он кеширует путь просмотра. Например, это будетviews/my_views.ejsПути кэшируются и привязываются к движку EJS.

    Express решает, кэшировать ли файлы просмотра двумя способами:

    Документировано: по телефонуapp.enabled("view cache")на. По умолчанию он отключен в режиме разработки, но вы можете включить его в рабочей среде. Конечно можно пройтиapp.disable("view cache")Закрыть вручную.

    Недокументировано: в соответствии с контекстом первого шагаcacheявляется ли объектtrueчтобы решить, следует ли кэшировать файл. Это позволяет настраивать параметры для каждого файла.

  3. Затем Express задает имя файла представления и используемый механизм просмотра. Если вы уже выполнили кэширование представлений на втором шаге, вы можете сразу перейти к последнему шагу. В противном случае перейдите к следующему шагу.

  4. Завершите просмотр файлов с отсутствующими расширениями в соответствии с механизмом просмотра по умолчанию. В этом примереaboutбудет расширен доabout.jadecontact.ejsа также404.htmlФайл будет сохранен без изменений. Если вы не укажете механизм просмотра по умолчанию и не укажете расширение, программа вылетит.
  5. Просмотр соответствия движка по расширению файла. за.htmlформатировать файл в соответствии сapp.engine("html", xx);установить, чтобы соответствовать.
  6. В папке представления найдите файл, соответствующий имени файла представления. Если он не существует, будет сообщено об ошибке.
  7. Определите, нужно ли кэшировать найденный файл представления.
  8. Используйте движок для рендеринга файла представления и создания окончательного HTML-файла.

Одновременное использование нескольких механизмов просмотра делает программу ненужной сложностью, но в большинстве случаев мы этого не делаем.

Ответом по умолчанию от Express клиенту является HTML. Хотя в большинстве случаев это нормально, иногда вы можете захотеть вернуть обычный текст, XML, JSON и т. д. На этом этапе вы можете изменить параметры,res.typeЧтобы выполнить пользовательские настройки:

app.get(“/”, function(req, res) { 
  res.type(“text”); 
  res.render(“myview”, { 
   currentUser: “Gilligan” 
  }); 
}

Конечно, вы можете использовать более простойres.json

Экспресс-совместимые настройки для View Engines: Consolidate.js

Помимо EJS и Pug, на самом деле существует множество шаблонизаторов. Но эти механизмы шаблонов могут быть не разработаны специально для Express, как EJS и Pug. На данный момент, если нам нужно использовать эти неадаптированные механизмы шаблонов, мы должны использоватьConsolidate.jsОбернут для совместимости с Express API. И Consolidate.js поддерживает множество типов, вы можете увидеть полный список поддерживаемых на домашней странице проекта.

Предположим, прямо сейчас вы используете Walrus, который несовместим с Express. Итак, давайте посмотрим, как работает Consolidate для обеспечения совместимости.

Во-первых, используйтеnpm install walrus consolidateУстанавливаем соответствующие библиотеки классов и зависимости, а затем импортируем их:

var express = require("express");

var engines = require("consolidate");
var path = require("path");
var app = express();

app.set("view engine", "wal");
app.engine("wal", engines.walrus);
app.set("views", path.resolve(__dirname, "views"));

app.get("/", function(req, res) {
    res.render("index");
});
app.listen(3000);

Разве это не просто? Всего за несколько строк кода мы завершили всю адаптацию. Поэтому, когда возникает необходимость в совместимости и адаптации, я настоятельно рекомендую вам использовать Consolidate вместо того, чтобы делать это самостоятельно.

Что вы должны знать в EJS

EJS — один из самых простых и популярных механизмов просмотра в Express. Он может создавать шаблоны для строк, HTML, обычного текста, и его интеграция очень проста. Он отлично работает как в браузере, так и в среде Node. Это очень похоже на ERB и методы в Ruby.

На самом деле существуют две разные версии EJS, поддерживаемые разными организациями. Хотя функционально они похожи, они не являются одной и той же библиотекой классов. EJS, используемый в Express, поддерживается TJ Holowaychuck, и вы можете найти библиотеку через npm. другой с таким же именембиблиотека классовОн был прекращен в 2009 году и не работает в среде Node.

EJS-синтаксис

Помимо использования в качестве шаблона HTML, его также можно использовать в строках и обычном тексте. Посмотрите, как EJS отображает следующий текстовый шаблон:

Hi <%= name %>!
You were born in <%= birthyear %>, so that means you're <%= (new Date()).getFullYear() - birthyear %> years old.
<% if (career) { -%>
  <%=: career | capitalize %> is a cool career!
<% } else { -%>
  Haven't started a career yet? That's cool.
<% } -%>
Oh, let's read your bio: <%- bio %> See you later!

Передайте следующие данные JSON в приведенный выше шаблон:

{
    name: "Tony Hawk",
    birthyear: 1968,
    career: "skateboarding",
    bio: "<b>Tony Hawk</b> is the coolest skateboarder around."
}

В конце концов, результирующий рендеринг (при условии, что текущий год - 2015):

Hi Tony Hawk!
You were born in 1968, so that means you’re 47 years old.
Skateboarding is a cool career!
Oh, let’s read your bio: Tony Hawk is the coolest skateboarder around. See
you later!

В этом примере демонстрируются четыре синтаксиса, обычно используемые EJS: печать, печать и экранирование, выполнение кода JS и фильтрация.

В EJS вы можете напечатать значение выражения, используя два синтаксиса: <% %> и <%- %>, где первое будет экранировать результат в формате HTML. Например, при поступленииexpressionзначение Express , результатом предыдущего выполнения является Express И строка, которую получает последний,Express. Я рекомендую вам использовать первый способ, так как он более надежен.

Также EJS позволяет выполнять в нем JS-выражения через синтаксис <%expression%>, при этом выражение не будет напечатано. Эта функция очень полезна при выполнении циклов и условных суждений. Кроме того, вы также можете пройти<% expression -%>Избегайте ненужных разрывов строк.

С помощью синтаксиса <% | xxx %> мы можем снова отфильтровать результат выражения. Например, выше мы применили фильтр капитализации к результату выражения. Конечно, в дополнение к большому количеству фильтров, которые поставляются с ним, вы также можете настроить его.

Здесь я сделал пример EJSпрограмма. Хотя интерфейс не очень красивый, но вы можете ознакомиться с различными синтаксисами EJS.

Встраивание других шаблонов EJS в существующие файлы EJS

Механизм EJS позволяет использовать другой шаблон EJS в текущем шаблоне. Таким образом, мы можем разделить и повторно использовать весь компонент. Например, разделение заголовка и хвоста HTML наheaderиfooterмодули, а затем объединяются и повторно используются в других шаблонах.

Пример следующий: сначала мы создаемheader.ejsи скопируйте код:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="/the.css">
    <title><%= appTitle %>/title>
</head>
<body>
    <header>
        <h1><%= appTitle %></h1>
    </header>

Затем создайте компонент нижнего колонтитулаfooter.ejsи скопируйте код:

<footer>
    All content copyright <%= new Date().getFullYear() %> <%= appName %>.
</footer>
</body>
</html>

Наконец, мы проходимincludeСинтаксис для встраивания компонента:

<% include header %>
    <h1>Welcome to my page!</h1>
    <p>This is a pretty cool page, I must say.</p>
<% include footer %>

Предположим, вам сейчас нужно реализовать компонент, отображающий информацию о пользователе, тогда вы можете создатьuserwidget.ejsфайл и скопировать:

<div class="user-widget">
    <img src="<%= user.profilePicture %>">
    <div class="user-name"><%= user.name %></div>
    <div class="user-bio"><%= user.bio %></div>
</div>

Затем шаблон можно использовать следующим образом при рендеринге текущего пользователя:

<% user = currentUser %>
<% include userwidget %>

или при отображении списка пользователей:

<% userList.forEach(function(user) { %>
  <% include userwidget %>
<% } %>

через EJSincludeсинтаксис, мы можем использовать его как компонент для рендеринга подпредставлений при создании шаблона.

###Добавьте свой собственный фильтр
В Express встроено 22 фильтра, включая стандартные операции над массивами и строками. Обычно их более чем достаточно для ваших нужд, но иногда приходится добавлять свои фильтры.

Предположим, теперь вы импортировали модуль EJS и сохранили его в файл с именемejsв переменной. Тогда вы можете сделать это следующим образомejs.filtersРасширяет фильтр для суммирования массивов.

ejs.filters.sum = function(arr) {
  var result = 0;
  for (var i = 0; i < arr.length; i++) {
    result += arr[i];
  }
  return result;
};

Затем вы можете использовать фильтр в своем коде:

<%=: myarray | sum %>

Его очень просто реализовать и использовать, поэтому я рекомендую вам реализовать эти общие операции в виде фильтров.

Что вы должны знать о мопсе

Механизмы просмотра, такие как Handlebars, Mustache и EJS, просто расширяют HTML с помощью нового синтаксиса, который не нарушает синтаксис HTML. Это лучше всего подходит для дизайнера, который знает синтаксис HTML без необходимости изучения нового языка. Они также работают в средах шаблонов, отличных от HTML, что является слабым местом Пага.

Но у Мопса есть и свои уникальные преимущества. Это уменьшает количество кода, который у вас есть, и стиль кода очень приятный. Особенно при написании шаблонов HTML теги вложены друг в друга и имеют отступ, и их не нужно закрывать. Кроме того, встроены синтаксис циклов и синтаксис EJS-стиля. Хотя есть чему поучиться, он также невероятно мощный.

Синтаксис мопса

Такие языки, как HTML, являются вложенными, с корневым элементом ( ) и различными дочерними элементами (такими как и ), которые могут дополнительно вкладывать другие элементы. Кроме того, HTML-элементы должны быть закрыты, как и XML.

Pug использует другой синтаксис отступов. Следующий код показывает простую веб-страницу, реализованную с помощью Pug:

doctype html
html(lang="en") 
  head
    title Hello world!
  body
    h1 This is a Pug example
    #container 
      p Wow.

Содержимое приведенного выше кода будет преобразовано в следующий HTML.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Hello world!</title>
</head 
    <body>
        <h1>This is a Pug example</h1>
        <div id="container">
            <p>Wow.</p>
        </div>
    </body>
</html>

Вы можете перейти на проект МопсДомойПосмотрим, как было достигнуто это преобразование.

Макет мопса

Важная особенность всех языков шаблонов при верстке. Это позволяет нам реализовывать общие компоненты, а затем повторно использовать их в других файлах. Например, мы можем извлечь верхний и нижний колонтитулы страницы. Это не только обеспечивает согласованность содержимого верхнего и нижнего колонтитула всех страниц, но и делает его более удобным для изменения.

Шаги реализации макета мопса примерно являются примерно следующими:

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

doctype html
html
  head
    meta(charset="utf-8")
    title Cute Animals website
    link(rel="stylesheet" href="the.css")
    block header  
  body
    h1 Cute Animals website
    block body

Вы можете увидеть определение вышеheaderиbodyДва заполнителя. Ниже мы сохраняем его вlayout.jadeв файле. Далее реализуемbodyкусок:

extends layout.jade
block body
  p Welcome to my cute animals page!

layout.jadeбудет отображаться как:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Cute Animals website</title>
    <link rel="stylesheet" href="the.css">
  </head>
  <body>
    <h1>Cute Animals website</h1>
    <p>Welcome to my cute animals page!</p>
  </body>
</html>

Обратите внимание, что при расширении основного макета вам не обязательно реализовывать в нем все заполнители. Например, вышеописанное не реализованоheader.

на других страницахbodyБлоки имеют разные реализации:

extends layout.jade
block body
  p This is another page using ths layout.
  img(src="cute_dog.jpg" alt="A cute dog!")
  p Isn't that a cute dog!

Разделение компонентов с помощью компоновки в Pug позволяет избежать некоторого дублирования кода.

Особенность миксинов мопса

В Pug также есть интересная функция под названием Mixins. С помощью этой функции вы можете определить один раз в файле функции, которые, возможно, потребуется использовать повторно. Далее мы будем использовать эту функцию для повторной реализации функций предыдущей части EJS для отображения информации о пользователе:

mixin user-widget(user)
  .user-widget
    img(src=user.profilePicture)
    .user-name= user.name
    .user-bio= user.bio

// 展示当前用户
+user-widget(currentUser)  

// 展示用户列表
- each user in userList 
  +user-widget(user)

На этом основной контент Pug заканчивается.Для получения дополнительной информации о синтаксисе посетите официальный сайт.Документация.

Суммировать

Содержание этой главы включает в себя:

  • Система просмотра Express и то, как она динамически отображается.
  • Синтаксис и базовое использование движка EJS.
  • Синтаксис и основное использование движка Pug.

оригинальныйадрес