Skip to content

Commit

Permalink
Merge a887ed5 into 742fd31
Browse files Browse the repository at this point in the history
  • Loading branch information
godfreyd committed Feb 23, 2018
2 parents 742fd31 + a887ed5 commit 498c8be
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 96 deletions.
246 changes: 190 additions & 56 deletions common.docs/i-bem-js/i-bem-js-common.ru.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,220 @@
## Общие сведения
## Знакомьтесь: 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), которая позволяет:

* Предоставлять модули асинхронно (`provide`).
* Подключать модули асинхронно (`require`).
* Переопределять и доопределять модули.

`i-bem.js` состоит из двух основных модулей:

* [bem-tools](https://ru.bem.info/toolbox/bem-tools/)
* [ENB](https://ru.bem.info/toolbox/enb/)
* **i-bem**.

Оба инструмента позволяют автоматизировать создание HTML-разметки для [привязки JS-блоков](./i-bem-js-html-binding.ru.md#Привязка-js-блоков-к-html) и [передачи параметров экземпляру блока](./i-bem-js-params.ru.md#Передача-параметров-экземпляру-блока-и-элемента).
JavaScript реализация блока `i-bem`. Модуль рассчитан на использование в любом JS-окружении: как на клиенте, так и на сервере (например, в Node.js).

### Почему i-bem.js так называется
Для декларации HTML-элемента в модуле `i-bem`, необходимо вызвать метод `bem.declBlock()`:

В соответствии с БЭМ-методологией, базовая JS-библиотека БЭМ-платформы изначально разрабатывалась как особый служебный блок. Такой подход позволяет работать с базовыми библиотеками так же, как и с обычными блоками. В частности, структурировать код в терминах элементов и модификаторов и гибко настраивать поведение библиотеки на разных уровнях переопределения.
```js
modules.define('page', ['i-bem'], function(provide, bem){
// Декларируем блок page в модуле i-bem
provide(bem.declBlock(this.name, {

Служебным блокам в БЭМ было принято давать имена с префиксом `i-`. Таким образом, имя `i-bem.js` читается как *реализация блока `i-bem` в технологии `JS`*.
}));
});
```

### Как использовать i-bem.js
* **i-bem-dom**.

Фреймворк `i-bem.js` входит в состав библиотеки [bem-core](https://ru.bem.info/platform/libs/bem-core/).
[Виртуальная DOM](#Виртуальная-dom) (JavaScript реализация DOM). Модуль рассчитан на использование на клиенте.

Реализация `i-bem.js` состоит из двух модулей:
Для декларации HTML-элемента в модуле `i-bem-dom`, необходимо вызвать метод `bemDom.declBlock()`:

* **Модуль [i-bem](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, {

Предоставляет базовую реализацию JS-блока `i-bem`, от которой наследуются все блоки и элементы в `i-bem.js`. Блок `i-bem` написан с расчетом на использование в любом JS-окружении: как на клиенте, так и на сервере (например, в Node.js).
}));
});
```

* **Модуль [i-bem-dom](https://ru.bem.info/platform/libs/bem-core/)**.
> **Примечание.** Зависит от библиотеки [jQuery](https://jquery.com), поэтому отдельная установка не требуется. Все методы jQuery доступны по умолчанию.
Предоставляет базовую реализацию блока и элемента, привязанных к DOM-узлу. Рассчитан на использование на клиенте, опирается на работу браузеров с DOM. Зависит от `jQuery`.
### Простой компонент

Зависимости:
Как отмечалось выше, для декларации компонента в [виртуальной DOM](#Виртуальная-dom), необходимо вызвать метод `bemDom.declBlock()`. Метод принимает имя [БЭМ-сущности](https://ru.bem.info/methodology/key-concepts/#БЭМ-сущность) и реализует взаимодействие с ней.

* 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) — для динамических проектов.
14 changes: 0 additions & 14 deletions common.docs/i-bem-js/i-bem-js-extras.en.md

This file was deleted.

Loading

0 comments on commit 498c8be

Please sign in to comment.