-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
211 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,214 @@ | ||
## Общие сведения | ||
## Знакомьтесь: i-bem.js | ||
|
||
### БЭМ-методология и JavaScript | ||
* [Введение в компонентный подход](#Введение-в-компонентный-подход) | ||
* [Виртуальная DOM](#Виртуальная-dom) | ||
* [Настройка страницы](#Настройка-страницы) | ||
* [Модульная система i-bem.js](#Модульная-система-i-bemjs) | ||
* [Простой компонент](#Простой-компонент) | ||
* [Несколько компонентов](#Несколько-компонентов) | ||
|
||
В БЭМ-методологии веб-интерфейс строится из независимых **блоков** у которых могут быть **элементы**. И блоки, и элементы могут иметь состояния или особенности, описываемые **модификаторами**. | ||
### Введение в компонентный подход | ||
|
||
Работа веб-интерфейса обеспечивается несколькими **технологиями** (HTML, CSS, JS и т.д.). Его реализация разбита на компоненты по блокам. Блок содержит набор **файлов технологий**, составляющих аспекты его реализации: | ||
|
||
* `my-block.css` — внешний вид блока; | ||
* `my-block.bemhtml` — шаблоны для генерации HTML-представления блока; | ||
* `my-block.js` — **динамическое поведение** блока в браузере. | ||
### Виртуальная DOM | ||
|
||
Фреймворк `i-bem.js` позволяет разложить клиентский JavaScript на компоненты в терминах БЭМ: | ||
HTML — это набор инструкций, на основе которых браузер строит DOM. Когда браузер загружает код HTML, его элементы становятся элементами DOM. | ||
|
||
* **Блок** — JS-компонент, описывающий логику работы однотипных элементов интерфейса. Например, все кнопки могут быть реализованы в виде блока `button`. В этом случае, `button.css` определяет внешний вид всех кнопок, а `button.js` — логику их работы. На каждой странице может размещаться более одного **экземпляра блока** (например, кнопки). Каждому экземпляру блока соответствует JS-объект, в памяти браузера, хранящий его состояние. JS-объект содержит ссылку на DOM-узел, к которому привязан данный экземпляр блока. | ||
* **Элементы** — DOM-узлы, вложенные в DOM-узел блока, с атрибутом `class`, указывающим на их роль в БЭМ-предметной области (имя блока и элемента). Элементы блока доступны через [JS-API](./i-bem-js-states.ru.md#Управление-модификаторами) экземпляра блока. | ||
* **Модификаторы** — предоставляют информацию о состоянии блока и его элементов. Состояние модификаторов записывается в атрибуте `class` на DOM-узлах блока и элементов. Управление модификаторами производится через [JS-API](./i-bem-js-states.ru.md#Управление-модификаторами) экземпляра блока. | ||
HTML-элементы связаны друг с другом в иерархии: существуют родительские и дочерние элементы. Последнии, в свою очередь, могут быть родительскими для других элементов. | ||
|
||
### Сборка | ||
С появлением Ajax добавление новых HTML-элементов на страницу с небольшими порциями данных стало обычным делом. Изначально браузер загружает один HTML-документ. В ходе взаимодействия пользователя со страницей, JavaScript выполняет работу по разбору DOM и добавлению новых элементов интерфейса. | ||
|
||
Разработка в рамках БЭМ-методологии ведется модульно — каждый блок программируется отдельно. Финальный исходный код веб-страниц формируется из кода отдельных блоков с помощью процедур **сборки**. | ||
Управление изменениями DOM с помощью JavaScript может стать очень сложным и затратным по времени. Часто такое управление выполняется императивно: | ||
|
||
В файловой системе блок удобно представлять в виде каталога, а реализацию блока в каждой из технологий — в виде отдельного файла: | ||
|
||
```html | ||
desktop.blocks/ | ||
my-block/ | ||
my-block.css | ||
my-block.js | ||
my-block.bemhtml | ||
... | ||
|
||
desktop.blocks/ | ||
other-block/ | ||
other-block.css | ||
other-block.js | ||
other-block.bemhtml | ||
... | ||
```js | ||
const h1 = document.createElement("h1"); | ||
h1.innerHTML = 'Hello, world!'; | ||
document.body.appendChild(h1); | ||
``` | ||
|
||
Для каждой веб-страницы код использованных на ней блоков может быть собран в единые файлы: | ||
`i-bem.js` помогает работать с DOM декларативно и не думать о том, как найти тот или иной элемент. Все HTML-элементы объявленные в `i-bem.js` имеют свой JavaScript объект с набором инструкций, применяемых для построения пользовательского интерфейса и взаимодействия с браузером. Таким образом, разработчик изменяет виртуальную модель DOM, а `i-bem.js` отображает эти изменения наиболее эффективным образом. | ||
|
||
```html | ||
desktop.bundles/ | ||
index/ | ||
index.html | ||
index.css | ||
index.js | ||
... | ||
### Настройка страницы | ||
|
||
Фреймворк `i-bem.js` входит в состав библиотеки [bem-core](https://ru.bem.info/platform/libs/bem-core/). Чтобы работать с `i-bem.js` в браузере, нужно подключить библиотеку на страницу. В примере ниже показано, как добавляется сценарий на страницу из Yаndex CDN. | ||
|
||
```diff index.html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Подключение i-bem.js</title> | ||
</head> | ||
<!-- Блок page --> | ||
<body class="page"> | ||
|
||
<!-- Библиотека bem-core --> | ||
+ <script src="https://yastatic.net/bem-core/latest/desktop/bem-core.no-autoinit.js"></script> | ||
<script> | ||
// Код i-bem.js и JavaScript | ||
</script> | ||
|
||
</body> | ||
</html> | ||
``` | ||
|
||
Существует два инструмента, поддерживающих БЭМ-предметную область, для сборки кода результирующих веб-страниц из отдельных описаний блоков: | ||
Это минимальные требования для работы с `i-bem.js` в браузере. Можно поместить ваш код JavaScript в отдельный файл, но он должен загружаться на страницу после загрузки `bem-core`. | ||
|
||
### Модульная система i-bem.js | ||
|
||
Модуль в `i-bem.js` представляет собой фрагмент кода, пригодный для многократного использования, который можно легко включить в другой модуль. | ||
|
||
`i-bem.js` использует модульную систему [ym/modules](https://github.com/ymaps/modules), которая позволяет: | ||
|
||
* [bem-tools](https://ru.bem.info/toolbox/bem-tools/) | ||
* [ENB](https://ru.bem.info/toolbox/enb/) | ||
* Предоставлять модули асинхронно (`provide`). | ||
* Подключать модули асинхронно (`require`). | ||
* Переопределять и доопределять модули. | ||
|
||
Оба инструмента позволяют автоматизировать создание HTML-разметки для [привязки JS-блоков](./i-bem-js-html-binding.ru.md#Привязка-js-блоков-к-html) и [передачи параметров экземпляру блока](./i-bem-js-params.ru.md#Передача-параметров-экземпляру-блока-и-элемента). | ||
`i-bem.js` состоит из двух основных модулей: | ||
|
||
### Почему i-bem.js так называется | ||
* **i-bem**. | ||
|
||
В соответствии с БЭМ-методологией, базовая JS-библиотека БЭМ-платформы изначально разрабатывалась как особый служебный блок. Такой подход позволяет работать с базовыми библиотеками так же, как и с обычными блоками. В частности, структурировать код в терминах элементов и модификаторов и гибко настраивать поведение библиотеки на разных уровнях переопределения. | ||
JavaScript реализация блока `i-bem`. Модуль рассчитан на использование в любом JS-окружении: как на клиенте, так и на сервере (например, в Node.js). | ||
|
||
Служебным блокам в БЭМ было принято давать имена с префиксом `i-`. Таким образом, имя `i-bem.js` читается как *реализация блока `i-bem` в технологии `JS`*. | ||
**Пример** | ||
|
||
### Как использовать i-bem.js | ||
```js | ||
modules.define('page', ['i-bem'], function(provide, bem){ | ||
// Декларируем блок page в модуле i-bem | ||
provide(bem.declBlock(this.name, { | ||
|
||
Фреймворк `i-bem.js` входит в состав библиотеки [bem-core](https://ru.bem.info/platform/libs/bem-core/). | ||
})); | ||
}); | ||
``` | ||
|
||
Реализация `i-bem.js` состоит из двух модулей: | ||
* **i-bem-dom**. | ||
|
||
* **Модуль [i-bem](https://ru.bem.info/platform/libs/bem-core/)**. | ||
[Виртуальная DOM](#Виртуальная-dom) (JavaScript реализация DOM). Модуль зависит от библиотеки [jQuery](https://jquery.com) (отдельная установка не требуется) и рассчитан на использование на клиенте. | ||
|
||
Предоставляет базовую реализацию JS-блока `i-bem`, от которой наследуются все блоки и элементы в `i-bem.js`. Блок `i-bem` написан с расчетом на использование в любом JS-окружении: как на клиенте, так и на сервере (например, в Node.js). | ||
**Пример** | ||
|
||
* **Модуль [i-bem-dom](https://ru.bem.info/platform/libs/bem-core/)**. | ||
```js | ||
modules.define('page', ['i-bem-dom'], function(provide, bemDom){ | ||
// Декларируем блок page в модуле i-bem-dom | ||
provide(bemDom.declBlock(this.name, { | ||
|
||
Предоставляет базовую реализацию блока и элемента, привязанных к DOM-узлу. Рассчитан на использование на клиенте, опирается на работу браузеров с DOM. Зависит от `jQuery`. | ||
})); | ||
}); | ||
``` | ||
|
||
Зависимости: | ||
### Простой компонент | ||
|
||
* jQuery (только для модуля `i-bem-dom`). При использовании `bem-core` отдельная установка jQuery не требуется. | ||
* Модульная система [ym/modules](https://github.com/ymaps/modules). При использовании [ENB](https://ru.bem.info/toolbox/enb/) с технологией `.browser.js` (и производных от нее) эта зависимость удовлетворяется автоматически. | ||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Простой компонент</title> | ||
</head> | ||
<!-- Блок page --> | ||
<body class="page i-bem" data-bem='{ "page": {} }'> | ||
|
||
<!-- Библиотека bem-core --> | ||
<script src="https://yastatic.net/bem-core/latest/desktop/bem-core.no-autoinit.js"></script> | ||
<script> | ||
modules.define('page', ['i-bem-dom'], function(provide, bemDom){ | ||
provide(bemDom.declBlock(this.name, { | ||
onSetMod: { | ||
js: { | ||
inited: function() { | ||
bemDom.prepend(this.domElem, '<h1 class="heading">Hello, world!</h1>'); | ||
} | ||
} | ||
}, | ||
})); | ||
}); | ||
// Инициализация | ||
modules.require('i-bem-dom__init', function(init) { init(); }); | ||
</script> | ||
|
||
</body> | ||
</html> | ||
``` | ||
|
||
### Несколько компонентов | ||
|
||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Несколько компонентов</title> | ||
</head> | ||
<!-- Блок page --> | ||
<body class="page i-bem" data-bem='{ "page": {} }'> | ||
<!-- Блок user --> | ||
<div class="user i-bem" data-bem='{ "user": {} }'></div> | ||
|
||
<!-- Библиотека bem-core --> | ||
<script src="https://yastatic.net/bem-core/latest/desktop/bem-core.no-autoinit.js"></script> | ||
<script> | ||
// Модуль блока page | ||
modules.define('page', ['i-bem-dom'], function(provide, bemDom){ | ||
provide(bemDom.declBlock(this.name, { | ||
onSetMod: { | ||
js: { | ||
inited: function() { | ||
bemDom.prepend(this.domElem, '<h1 class="heading">Hello, world!</h1>'); | ||
} | ||
} | ||
} | ||
})); | ||
}); | ||
// Модуль блока user | ||
modules.define('user', ['i-bem-dom'], function(provide, bemDom){ | ||
provide(bemDom.declBlock(this.name, { | ||
onSetMod: { | ||
js: { | ||
inited: function() { | ||
const user = 'Ben Reilly'; | ||
bemDom.prepend(this.domElem, '<h2 class="heading">Hello, '+ user +'!</h2>'); | ||
} | ||
} | ||
} | ||
})); | ||
}); | ||
// Инициализация | ||
modules.require('i-bem-dom__init', function(init) { init(); }); | ||
</script> | ||
|
||
</body> | ||
</html> | ||
``` | ||
|
||
JavaScript-реализацию каждого блока можно вынести в отдельные файлы и затем выполнить инициализацию модуля `i-bem-dom`: | ||
|
||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Несколько компонентов</title> | ||
</head> | ||
<!-- Блок page --> | ||
<body class="page i-bem" data-bem='{ "page": {} }'> | ||
<!-- Блок user --> | ||
<div class="user i-bem" data-bem='{ "user": {} }'></div> | ||
|
||
<!-- Библиотека bem-core --> | ||
<script src="https://yastatic.net/bem-core/latest/desktop/bem-core.no-autoinit.js"></script> | ||
<script src="page.js"></script> | ||
<script src="user.js"></script> | ||
<script> | ||
// Инициализация | ||
modules.require('i-bem-dom__init', function(init) { init(); }); | ||
</script> | ||
|
||
</body> | ||
</html> | ||
``` | ||
|
||
Можно использовать `i-bem.js` как часть полного стека БЭМ-инструментов. В этом случае свой проект удобно создавать на основе шаблонного репозитория [project-stub](https://ru.bem.info/platform/project-stub/), в котором настроена автоматическая установка зависимых библиотек и сборка. | ||
Чаще все JavaScript-реализации блоков [собирают в отдельный бандл](https://ru.bem.info/methodology/build/), который подключают на страницу. Тема сборки выходят за рамки этого документа, поэтому вы можете использовать готовые шаблонные репозитории, где сборка бандлов настроена по умолчанию: | ||
|
||
Если не планируется использование других технологий БЭМ-платформы, достаточно поместить код библиотеки `bem-core` в существующий проект. | ||
* [project-stub](https://github.com/bem/project-stub) — для статических проектов; | ||
* [bem-express](https://github.com/bem/bem-express) — для динамических проектов. |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.