Продолжаем облегчать себе ежедневную жизнь через одномоментную боль
В описании урока я написал про одномоментную боль — и это, к сожалению, фраза почти про любой инструмент разработчика: все эти шутки про настройки Вебпака не совсем лживы.
Тем не менее, не нужно расстраиваться! Нужно просто знать об этом и внимательно читать документации, гуглить и спрашивать в тематических чатах.
И помните про ошибки: они нужны, чтобы помочь вам, а не чтобы выбесить из себя. Если возникла ошибка — читайте её, гуглите и спрашивайте в чатах.
Окей, погнали! Сегодня будем прикручивать шаблонизатор.
Шаблон это интерфейс, который можно переиспользовать с разными данными.
Например, карточка ресторана, это один компонент, просто с разными данными: изображением, названием, категориями, средней ценой и временем доставки.
Было бы здорово, если бы у нас был отдельный компонент (или шаблон), который мы могли бы использовать несколько раз. Что-то типа
<template name="card">
<img src={imgSrc} />
<h3>{title}</h3>
<p>{priceCategory} • {category}</p>
<time>{deliveryTimeFrom} - {deliveryTimeTo} min</time>
</template>
<div class="container">
<div class="row">
<div class="col-md-3">
<card
imgSrc="https://i.imgur.com/v2lJHlY.png"
title="Кофемания на Трубной"
priceCategory="₽"
category="Европейская"
deliveryTimeFrom="30"
deliveryTimeTo="50"
>
</div>
</div>
</div>
Согласитесь, выглядит красиво? Поздравляю, мы написали шаблон (в теге template
) и его использовали. Конечно, это не заработает — это псевдокод.
Я бы даже сказал, что это близко к компонентам Реакта (седьмой урок курса по Реакту, но первые шесть нужно сначала пройти) — там тоже используются ХТМЛ-атрибуты для компонентов.
Окей, а как сделать так, чтобы заработало?
Шаблонизатор — это специальная утилита, которая компилирует шаблоны (например, из своего формата в тот же ХТМЛ). Самый популярный в вёрстке — это Паг (pug).
В базовом понимании шаблонизатор во время компиляции заменяет данные в шаблоне, но некоторые дают ещё дополнительные возможности.
Кому-то кажется. что ХТМЛ не очень удобен, поэтому они вводят свой синтаксис:
doctype html
html(lang='en')
head
title Pug
body
h1 Pug Examples
div.container
p Cool Pug example!
a(href='google.com') Google
Выглядит странновато, но кому-то нравится.
Как раз тот пример, с которого начался урок. Нам понадобятся миксины и импорты.
mixin article(title)
.article
.article-wrapper
h1= title // через = работаем с аргументами
if block // если есть ребёнок (он называется блоком) — отобразить
block
else // если нет, то отобразить заглушку
p No content provided
+article('Hello world') // вызываем через +
+article('Hello world')
p This is my
p Amazing article
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>No content provided</p>
</div>
</div>
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>This is my</p>
<p>Amazing article</p>
</div>
</div>
Но миксины работают если они находятся в одном файле. Как быть, если хочется держать миксин в отдельном? Например, в Card.pug
.
Официальная документация не очень помогает, поэтому пришлось гуглить «pug include with variables» и найти ответ на Стэковерфлоу.
Схема проста: в одном файле мы объявляем миксин, в другом — подключаем через include
и используем.
// Card.pug
mixin Card(title, imgSrc, priceCategory, category, deliveryTimeFrom, deliveryTimeTo)
.card
img(src=imgSrc)
h3= title
p #{priceCategory} • #{category} // со значениями можно работать и через #{}
time #{deliveryTimeFrom} - #{deliveryTimeTo}
// List.pug
include Card.pug
.list
+Card("Кофемания на Трубной", "https://i.imgur.com/v2lJHlY.png", "₽", "Европейская", 30, 50)
Во многих шаблонизаторах (кстати, ещё один популярный — Хэндлбарс) есть поддержка кейсов, циклов и условий. Здесь документация уже справляется.
Окей, мы написали эти шаблоны, но браузер же не поддерживает .pug
или .hjs
, нам нужно их перевести в ХТМЛ. Этот процесс называется компиляцией.
На главной странице Пага вторым параграфом идёт описание этого процесса:
The general rendering process of Pug is simple.
pug.compile()
will compile the Pug source code into a JavaScript function that takes a data object (called “locals
”) as an argument. Call that resultant function with your data, and voilà!, it will return a string of HTML rendered with your data.
Нам тут понадобится создать файл compile-templates.js
и написать небольшой Джс.
// src/index.pug
doctype html
html
head
title UberEats
...
// compile-templates.js
const pug = require("pug");
// скомпилируем
const compiled = pug.compileFile("src/index.pug");
// отрендерим и выведем в консоль
// через метод `console.log()`
console.log(compiled());
// "<!doctype html><html><head><title>UberEats</title>...</head></html>"
Это задание добровольное — не всем нужны шаблонизаторы
Переведите свою вёрстку на Паг и не забудьте воспользоваться gulp-pug
: держать файл compile-pug.js
не очень удобно.
Сегодня мы познакомились с шаблонизаторами — утилитами, которые оптимизируют наш код, приводя его к шаблонам.
Может быть, вам не всегда будет нравиться их синтаксис, но облегчать жизнь они облегчают.
Как вы могли заметить, здесь у нас пропаганда Реакта — что уж поделать, он стал стандартом во фронтэнде.
Не в последнюю очередь благодаря своему Джсх — чисто технически, это не совсем шаблонизатор, но можно назвать и так.
Пока у остальных библиотек и фреймворков типа Ангулара или Вью свой птичий язык уровня Пага или Хэндлбарс, у Реакта — Джсх, который очень красиво интегрирует обычный Джаваскрипт с ХТМЛ.
Посмотрите на это:
// src/index.js
// в props — объект со всеми атрибутами
function Card(props) {
return (
<a href={props.href}>
<img src={imgSrc} />
<h3>{title}</h3>
<p>{priceCategory} • {category}</p>
<time>{deliveryTimeFrom} - {deliveryTimeTo} min</time>
</a>
)
}
function List() {
return (
<div class="container">
<div class="row">
<div class="col-md-3">
<Card
imgSrc="https://i.imgur.com/v2lJHlY.png"
title="Кофемания на Трубной"
priceCategory="₽"
category="Европейская"
deliveryTimeFrom={15+15}
deliveryTimeTo={25*2}
>
</div>
</div>
</div>
)
}
Весь секрет в том, что в Джсх в {}
можно выполнять любой Джаваскрипт-код. Обратите внимание на атрибуты (здесь они называются пропами, props
) deliveryTimeFrom
и deliveryTimeTo
— там обычный Джаваскрипт.
Подробнее, как вы понимаете, в первом этапе курса по Реакту. Велкам!