Введение
На прошлых вебинарах с Димой Белицким мы сверстали простую страницу следуя БЭМ-методологии: написали HTML и CSS, немного декларативного JavaScript, а также настроили сборку с помощью gulp.
В этом вебинаре мы получим BEMJSON имеющихся страниц, напишем простые BEMHTML-шаблоны и посмотрим на некоторые интересные возможности BEMHTML.
Итак, немного про декларативные шаблоны.
Все привыкли к декларативной природе CSS, поэтому удобно провести аналогию.
Допустим, у нас есть список:
<ul class="menu">
<li class="menu__item">
Привет
<li>
<li class="menu__item">
BEM!
<li>
</ul>
Чтобы задать определенный внешний вид всем элементам списка можно написать CSS:
.menu__item {
background: red;
}
А если же хочется изменить связку ul
+ li
, например, на nav
+ a
? Что если это можно было бы сделать по аналогии с CSS, написав соответствующий «селектор» и просто задать другое значение свойству tag
?
Так это выглядит в BEMHTML:
block('menu')(
tag()('nav')
)
block('menu').elem('item')(
tag()('a')
)
Чтобы иметь возможность таким образом пребразовывать HTML необходима особая декларация страницы.
BEMJSON
BEMJSON — это описание структуры страницы в терминах БЭМ на JavaScript с зарезервированными полями. Указанный ранее список в BEMJSON описывается так:
({
block: 'menu',
tag: 'ul',
content: [
{
elem: 'item',
tag: 'li',
content: 'Привет'
},
{
elem: 'item',
tag: 'li',
content: 'BEM!'
}
]
})
BEMJSON компилирутся в HTML.
Избавиться от копипасты tag: 'li'
поможет BEMHTML-шаблон.
block('menu')(
tag()('ul')
)
block('menu').elem('item')(
tag()('li')
)
BEMHTML-шаблон накладывается на BEMJSON по аналогии с тем, как CSS накладывается на DOM-дерево. На выходе — получаем HTML.
BEMJSON для наших страниц
Код — 01858d
Если есть HTML, написанный по БЭМ, то BEMJSON можно получить автоматически с помощью пакета html2bemjson
npm install html2bemjson
Сборка
Код — eef725
Далее нужно дотюнить сборку:
- gulp научился собирать зависимости по BEMJSON, а не HTML
- добавился таск для компиляции HTML по BEMJSON с использованием BEMHTML-шаблонов
Вычисления во время компиляции в BEMJSON
Код — 51ec21
BEMJSON представляет собой plain JavaScript, поэтому позволяет любые вычисления во время компиляции — то, чего не достает HTML.
Например,
({
block: 'menu',
// построим BEMJSON списка динамически из массива текстов элементов
content: [
'Привет',
'BEM!'
].map(function(text) {
return {
elem: 'item',
content: text
};
})
})
({
block: 'menu',
// определим массив текстов динамически,
// который будет разным при каждой генерации итогового HTML
content: (function() {
return Math.random() > 0.5 ? ['Привет'] : ['Привет', 'BEM!'];
}()).map(function(text) {
return {
elem: 'item',
content: text
};
})
})
Напишем простые BEMHTML-шаблоны
Код — 17d9a6
Упростим полученный автоматической конвертацией BEMJSON:
- вынесем всю HTML-обвязку страницы в блок
page
- упростим представление меню в BEMJSON, сгенерировав BEMJSON самого списка элементов в шаблоне
- напишем простой шаблон для ссылки
Специальные возможности BEMHTML
Код — bad312
Шаблонизатор BEMHTML имеет некоторые интересные возможности:
Переопределение в зависимости от входных данных
Например, блок link
должен быть представлен в HTML span
-ом, а не ссылкой, если в BEMJSON не было поля url
.
Переопределение на уровне переопределения
Например, менюшка на странице с Поттером должна быть в HTML представлена тегом ol
, а на всех других страницах — ul
. Для этого достаточно определить блок меню на уровне potter.blocks
. После сборки всех шаблонов в один файл получим:
// common.blocks
block('menu')(...)
// potter.blocks
block('menu')(...)
По аналогии с CSS, последнее «правило» перебивает предыдущее.
Привет!
А подскажите, пожалуйста, можно ли сюда же ещё впилить deps, или что-то похожее, чтобы собирать зависимости? Как я понял, сейчас этого нет.
Я поискал, нашёл некоторые упоминания gulp-bem, который вроде бы умеет то, что мне нужно (например, в iamstarkov/gulp-bem-stub), но может быть есть способ использовать здесь зависимости без gulp-bem.
Самое простое из доступного для полноценной сборки deps на сегодняшний день — это сборка на
gulp
в веткеproject-stub
: https://github.com/bem/project-stub/blob/feature/gulp/gulpfile.js (это неgulp-bem-stub
по ссылке выше — там используется альтернативная реализация депс).Подробнее про история со сборкой на БЭМ-проектов на gulp можно почитать тут: https://github.com/bem/bem-forum-content-ru/issues/782
@tadatuta Изначально я именно с той статьи, на которую вы сослались, и начал. Но там, по сравнению с этим вебинаром, как-то много всего используется, а хотелось просто чтобы зависимости подключались.
Но спасибо за помощь, буду разбираться дальше.
чуваки, выложите ваше видео беминаров, пожалуйста. Спасибо.
@weynemeynen Первый: https://ru.bem.info/forum/-661/ Второй: https://ru.bem.info/forum/-685/ Третий: https://ru.bem.info/forum/-696/
А четвёртый сам найти не могу :с
Есть еще пятый: https://www.youtube.com/watch?v=OBjKCY3TiJg А четвертый недоступен по техническим причинам, поэтому Витя написал подробную статью.
там ещё пятый должен быть с В. Гриненко
вот это то что нужно. Спасибо.
@tadatuta О_О Когда видел репозиторий по пятому, думал, это заготовка. Оказывается, когда-то пропустил бэминар. Пора навёрстывать. Спасибо за видео :)
@igoradamenko
Это, кстати, интересно — у меня есть подозрение, что не все наши письма с приглашениями долетают до пользователей :(
Скажи, я правильно понял, что ты участвовал в предыдущих бэминарах, а письмо про пятый не получил?
// cc @deeonis
@tadatuta Подписался на рассылку после первого или второго. В 3-м и 4-м точно участвовал; письма точно приходили.
Не помню, чтобы я получал письмо про пятый. Мне кажется, что его не было, иначе я хотя бы знал о том, что бэминар состоялся.
@igoradamenko Спасибо, будем разбираться, где мы продолбали.
@tadatuta видео не доступно.
@ilyar Уверены? У меня работает.
@ilyar На всякий случай залил: https://yadi.sk/i/7dUde7j3pz8P8
@igoradamenko уверен, если смотреть с форума:
Сейчас понял, что можно перейти по ссылке, которую видно на
GitHub
, тогда работает:Спасибо!