Мы шаг за шагом создадим страничку каталога товаров, пользуясь принципами БЭМ в CSS, возможностями писать декларативный JavaScript на фреймворке
i-bem.js и с использованием шаблонизатора BEMHTML. Помогать делать всё это будут bem tools, в частности — инструмент для разработки bem server.
Важно: в статье нет особенных подробностей, её цель — получить проект максимально быстро. Текст, раскрывающий больше информации, пройдёт следующим постом.
Что такое БЭМ?
Для начала небольшое лирическое отступление для тех, кто не в курсе, что обозначает эта аббревиатура.
БЭМ расшифровывается как «Блок, Элемент, Модификатор». Это методология разработки web-проектов, способ удобно делить интерфейс на отдельные штучки, применимый для любой технологии. Кроме того, БЭМ — это набор инструментов для автоматизации работы. И наконец, БЭМ — это возможность создания интерфейсных библиотек для быстрой и эффективной разработки.Если ранее вы не сталкивались с БЭМ, вам стоит вначале просмотреть материалы сайта bem.info, а затем вернуться к этой статье.
Для тех, кому больше нравится видео, могу предложить запись доклада с WebConf Riga 2012 (на английском) или выступление Сергея Бережного (veged) на РИТ 2011.
Необходимые инструменты
Чтобы пройти по всем шагам этого мануала, вам нужно установить bem tools. Это набор инструментов с command line интерфейсом для оперирования БЭМ-сущностями и сборки проекта. Инструкция по установке есть в описании репозитория.
Создание собственного репозитория проекта
Проще всего создать свой проект простым копированием существующего репозитория с подходящей структорой. Для проекта с использованием полного стека БЭМ подойдёт репозиторий project-stub.
$ git clone git://github.com/bem/project-stub.git my-pretty-project $ cd my-pretty-project/ $ rm -rf .git $ git init
Затем проект нужно собрать. Для этого запускается команда
make
Это занимает некоторое время, потому что именно в этот момент в директорию проекта устанавливаются все необходимые npm-пакеты.
В конце вы увидите следующее сообщение:
info: Server is listening on port 8080. Point your browser to http://localhost:8080/
На вашем компьютере запустился bem server — инструмент для разработки, который будет автоматически пересобирать ваш проект, если вы внесете в него изменения.
Внесение изменения в страницы
Сейчас на вашем проекте есть одна страница index.html, которую вы можете открыть в браузере.
Первый запрос к странице будет обрабатываться заметное время, потому что в этот момент bem server подгружает необходмые для её сборки библиотеки.
Структура проекта предполагает, что блоки будут размещены в директории desktop.blocks, а страницы — в директории desktop.bundles.
Вообще, строго говоря, desktop.bundles хранит «набор» блоков. Это могут быть частоиспользуемые блоки нескольких страниц (то, что обычно называют common), наборы, объединяющие несколько страниц (all, если объединены все страницы) или — самый простой случай — наборы блоков, каждый из которых соответствует одной странице. Здесь будет рассматриваться последний, простой вариант.
Вы можете отредактировать страницу, меняя файл desktop.bundles/index/index.bemjson.js.
Описание блока в bemjson
Сначала мы разместим на странице Шапку. В терминах БЭМ это блок head:
{ block: 'head' }
Здесь и далее полный код страницы на разных стадиях можно будет находить на Gist: https://gist.github.com/4175550.
Перезагрузив страницу, вы увидите что в ней появился соответствующий <div>.
Шапку мы наполним содержанием: форма поиска, логотип и раскладка, располагающая содержание как нужно.
Сначала в BEMJSON-описании страницы внутрь блока head помещаем блок layout с двумя элементами: left и right.
content: [ { block: 'head', content: { block: 'layout', content: [ { elem: 'left', content: 'left here' }, { elem: 'right', content: 'right here' } ] } } ]
https://gist.github.com/4175573
Это создаст необходимую разметку (вы можете увидеть её, обновив страницу), к которой нужно написать стили. То есть реализовать блок layout в технологии CSS.
Создание блока
Для создания файла технологии воспользуемся командой bem create.
$ bem create -l desktop.blocks/ -T css -b layout
Команда создаст файл desktop.blocks/layout/layout.css, в котором уже есть селектор, соответствующий файлу блока. Правило нужно дополнить соответственно назначению блока.
Сейчас можно просто скопировать: https://gist.github.com/4175598
Использование блоков из библиотек
Вложенные в layout блоки поисковой формы и логотипа реализовывать самостоятельно не нужно. Они уже реализованы в библиотеке bem-bl, достаточно просто задекларировать их на странице. То есть вставить BEMJSON-описание блока в страницу desktop.bundles/index/index.bemjson.js
Для нашей страницы мы воспользуемся блоками b-search и b-logo.
https://gist.github.com/4175640
Картинку для логотипа можно взять отсюда илиуказать свою.
Доопределение блоков библиотек
Доопределение в CSS
Используемый нами блок b-logo предоставляет только нужную разметку. CSS для неё каждый разработчик может написать сам, потому что всем нужна разная разметка.Эту разметку мы поместим в блок b-logo на своём уровне переопределения.
$ bem create -l desktop.blocks/ -T css -b b-logo
Разметку для блока можно взять отсюда: https://gist.github.com/4175675
То же самое для блока b-search:
$ bem create block -l desktop.blocks/ -T css b-search
https://gist.github.com/4195433
Доопределение BEMHTML
Чтобы сделать страницу центрированной, нужен дополнительный контейнер. Для этого мы доопределим шаблоны блока b-page, создав такой же блок на своём уровне. В качестве шаблонизатора используется BEMHTML3.
$ bem create -l desktop.blocks/ -b b-page -T bemhtml
В получившемся файле desktop.blocks/b-page/b-page.bemhtml нужно написать код, оборачивающий контент блока в дополнительный контейнер.
block b-page, content: { elem: 'body-i', content: this.ctx.content }
https://gist.github.com/4175742
Для получившейся разметки создаются свои CSS-правила:
$ bem create -l desktop.blocks/ -T css -b b-page
Контент для получившегося файла desktop.blocks/b-page/b-page.css можно скопировать отсюда: https://gist.github.com/4175763
А для того, чтобы блок шапки был заметен на странице, я задам ему border:
$ bem create -l desktop.blocks/ -T css -b head
Контент для файла desktop.blocks/head/head.css: https://gist.github.com/4175776.
BEMHTML шаблоны
BEMHTML шаблоны могут не просто определять теги, которым представлен блок, и их атрибуты, но и генерировать оформительский контент.
Например, давайте разместим на странице список товаров. Он представлен в BEMJSON-декларации страницы блоком goods, и декларация содержит необходимые данные.
{ block: 'goods', goods: [ { title: 'Apple iPhone 4S 32Gb', image: 'http://mdata.yandex.net/i?path=b1004232748_img_id8368283111385023010.jpg', price: '259', url: '/' }, { title: 'Samsung Galaxy Ace S5830', image: 'http://mdata.yandex.net/i?path=b0206005907_img_id5777488190397681906.jpg', price: '73', url: '/' }, ... }
https://gist.github.com/4176078
Для того, чтобы эти данные превратились в нужную разметку, блок должен быть реализован в технологии BEMHTML. Для внешнего вида — технология CSS. Поэтому можно создать блок во всех технологиях, предусмотренных по-умолчанию.
$ bem create -l desktop.blocks -b goods
В BEMHTML шаблоне блока desktop.blocks/goods/goods.bemhtml нужно написать код, который превратит JSON с данными в элементы блока. А также, пользуясь модой tag указать, какими DOM-элементами представить блок и его элементы.
block goods { tag: 'ul' ... elem item, tag: 'li' elem title, tag: 'h3' }
https://gist.github.com/4176118
Шаблон может создавать не только элементы блока, но и другие блоки. Например, цену товара можно завернуть в ссылку, используя для этого блок b-link из библиотеки bem-bl.
{ elem: 'price', content: { block: 'b-link', url: item.url, content: item.price } }
https://gist.github.com/4176996
Кроме того, для того, чтобы избежать каскада при оформлении этой ссылки стилями, её можно пометить как элемент блока goods.
{ block: 'b-link', mix: [{ block: 'goods', elem: 'link' }], url: item.url, content: item.price }
https://gist.github.com/4177113
Также нужно пометить элементы о новых товарах модификатором и добавить выравнивающих элементов.
https://gist.github.com/4177157
CSS для блока можно скопировать отсюда https://gist.github.com/4177163.
Создавать блок отдельно в технологии CSS не нужно, потому что он изначально был создан со всеми необходимыми файлами.
Понадобится и CSS для IE. Он не входит в список технологий по умолчанию.
$ bem create block -l desktop.blocks/ -T ie.css goods
Содержание для получившегося файла desktop.blocks/goods/goods.ie.css можно взять на Gist https://gist.github.com/4177174
Зависимости блоков
Помимо декларации нужно гарантировать подключение к странице шаблонов, CSS и JavaScript блока. Для этого у блока можно описать зависимости, это делается представлением блока в технологии deps.js.
$ bem create -l desktop.blocks/ -T deps.js -b goods
Можно воспользоваться нестрогой зависимостью shouldDeps, указав, что нужен блок b-link.
({ shouldDeps: [ { block: 'b-link' } ] })
https://gist.github.com/4177031
Подключение библиотек
Хочется представить шапку и каждый товар модными прямоугольниками с тенью. Блок для этого я позаимствую из библотеки моего друга.
Там есть всего один блок, который называется box и делает то, что мне нужно.
Чтобы получить код библиотеки, мне нужно указать её адрес в ./bem/make.js, по аналогии с соседними библиотеками.
getLibraries: function() { return { 'bem-bl': { type: 'git', url: 'git://github.com/bem/bem-bl.git', treeish: '0.3' }, 'bemhtml' : { type: 'git', url: 'git://github.com/bem/bemhtml.git' }, 'john-lib' : { type: 'git', url: 'git://github.com/john-johnson/j.git' } }; }
https://gist.github.com/4177229
А также указать в настройках бандлов (страниц), что этот уровень нужно использовать при сборке. Это делается в файле desktop.bundles/.bem/level.js.
exports.getConfig = function() { return BEM.util.extend(this.__base() || {}, { bundleBuildLevels: this.resolvePaths([ '../../bem-bl/blocks-common', '../../bem-bl/blocks-desktop', '../../bemhtml/common.blocks', '../../john-lib/blocks/', '../../desktop.blocks' ]) }); };
https://gist.github.com/4177250
К сожалению, пока что при изменении конфигурации проекта приходится перезапускать bem server. Текущий процесс придётся прервать и снова набрать команду make.
В будущих версиях необходимость перезапуска обещают убрать.
Миксы блоков и элементов
Теперь можно использовать блок box Я могу просто обернуть им мои блоки. Но чтобы сэкономить разметку, можно смешать на одной DOM-ноде 2 блока. Это называется mix.
Один из способов смешения — описать его во входных данных (BEMJSON).
В данном случае нужно смешать блок head с блоком box, изменив код страницы.
{ block: 'head', mix: [ { block: 'box' } ], content: ... }
https://gist.github.com/4177292
Не забудьте записать блок box в зависимости блока head
$ bem create -l desktop.blocks/ -T deps.js -b head ({ shouldDeps: [ { block: 'box' } ] })
https://gist.github.com/4235143
Смешивать можно не только блоки, но и элементы с блоками.
В шаблоне блока goods смешаем каждый элемент item с блоком box.
content.push({ elem: 'item', mods: mods, mix: [{ block: 'box' }], content: ...
https://gist.github.com/4177350
Декларативный JavaScript
Блоки с JavaScript функциональностью
Блок box, который появился у меня на проекте благодаря подключенной сторонней библиотеке, предоставляет также и динамическую JavaScript-функциональность — он умеет сворачиваться.
Для сообщения, что я хочу использовать эту JavaScript-функциональность в шапке, мне нужно изменить описание блока head, указав, что у примешиваемого блока box есть JavaScript-реализацию:
mix: [{ block: 'box', js: true }]
https://gist.github.com/4202622
Также требуется разместить внутри блока элемент switcher
content: [ { block: 'layout', ... }, { block: 'box', elem: 'switcher' } ]
https://gist.github.com/4202651
Получается блок со стрелочкой, которая умеет сворачивать и разворачивать его.
Доопределение JavaScript
Мне недостаточно JavaScript-функциональности блока box. Я хочу, чтобы он сворачивался не только по вертикали, но и по горизонтали. При этом вносить изменения в чужую библиотеку я не могу. Но благодаря тому, что JavaScript блока написан с использованием декларативного фреймворка из блока i-bem, у меня есть возможность изменить (переопределить или доопределить) поведение блока на своём уровне.
bem create -l desktop.blocks -T js -b box
В получившемся файле desktop.blocks/box/box.js нужно оставить только секцию onSetMod, описывающую реакцию на установку модификаторов.
onSetMod : { }
https://gist.github.com/4195865
В данном случае нужно реагировать на установку и снятие модификатора closed:
onSetMod : { 'closed': { 'yes': function() { // some functionality here }, '': function() { // some functionality here } } }
https://gist.github.com/4195879
Создание новых страниц
Страницы — это тоже блоки, на своём уровне переопределения. Поэтому для их создания тоже можно воспользоваться командой bem create:
bem create -l desktop.bundles -b contact
Флаг -T можно не указывать, потому что bem create благодаря настройкам уровня desktop.bundles знает, что создаваемые на этом уровне блоки должны быть представлены в технологии BEMJSON. Так, появляется файл desktop.bundles/contact/contact.bemjson.js с минимальным содержимым для страницы.
Новую страницу можно посмотреть по адресу http://localhost:8080/desktop.bundles/contact/contact.html
bem server соберёт её HTML, JS и CSS файлы в момент первого обращения.
Production deployment
Всё время, пока мы разрабатывали проект, работал bem server и пересобирал те части проекта, которые нуждаются в изменении при обновлении страниц.
Для выкатки в продакшен тоже нужна сборка проекта, но уже всего проекта целиком, вне зависимости от того, изменилось что-то или нет. Для этого можно воспользоваться командой bem make.
Рекомендуется запускать локальную для данного проекта версию пакета:
./node_modules/bem/bin/bem make
creadits За подготовку разметки сайта большое спасибо tyv и gela-d.
ссылка на оригинал статьи http://habrahabr.ru/post/162385/
Добавить комментарий