Инициализация
Инициализация — это создание в памяти браузера JS-объекта, соответствующего экземпляру блока или элемента. Инициализация экземпляров блоков или элементов выполняется функцией init([ctx]) из модуля i-bem-dom на заданном фрагменте DOM-дерева ctx.
Каждому экземпляру можно приписать три состояния:
не инициализирован — JS-объект не создан
инициализирован — JS-объект создан в памяти браузера
уничтожен — удалены все ссылки на JS-объект экземпляра, и он может быть удален сборщиком мусора.
В i-bem.js эти состояния описываются с помощью служебного модификатора js.
До инициализации экземпляр не имеет модификатора
js.
<div class="my-block i-bem" data-bem='{ "my-block" : {} }'>...</div>
В момент инициализации экземпляру устанавливается модификатор
jsв значенииinited.
<div class="my-block i-bem my-block_js_inited" data-bem='{ "my-block" : {} }'>...</div>
Если в процессе работы удаляется фрагмент DOM-дерева (при помощи метода
destruct()модуляi-bem-dom), то вместе с ним удаляются экземпляры, все HTML-элементы которых находятся в этом фрагменте. Перед удалением экземпляра модификаторjsудаляется, чтобы выполнились деструкторы экземпляра.
Примечание Если экземпляр блока или элемента был привязан к нескольким HTML-элементам, экземпляр будет существовать, пока в HTML-дереве сохраняется хотя бы один HTML-элемент, с которым он связан.
Если на HTML-элементе размещено несколько экземпляров других блоков или элементов, то инициализация одного из них (появление модификатора js со значением inited) не влияет на инициализацию остальных.
Пример
На HTML-элементе инициализирован только экземпляр блока my-block. Экземпляр блока lazy-block не инициализирован:
<div class="my-block my-block_js_inited lazy-block i-bem" data-bem='{ "my-block" : {}, "lazy-block" : {} }'>
...
</div>
Примечание Наличие модификатора
jsпозволяет писать разные CSS-стили для блока или элемента в зависимости от того, инициализирован он или нет.
Конструктор экземпляра блока и элемента
На изменение значений модификатора js можно назначать триггеры так же, как и для любых других модификаторов.
Триггер на установку модификатора js в значение inited выполняется при инициализации экземпляра.
Этот триггер можно считать конструктором:
bemDom.declBlock('my-block', {
onSetMod : {
'js' : {
'inited' : function() { /* ... */ } // конструктор экземпляра
}
}
});
Деструктор экземпляра блока и элемента
Моментом удаления экземпляра является момент уничтожения всех ссылок на его JS-объект, после чего он может быть удален из памяти браузера сборщиком мусора.
Триггер на удаление модификатора js (установку в пустое значение '') выполняется перед удалением блока. Такой триггер можно считать деструктором.
bemDom.declBlock('my-block', {
onSetMod : {
'js' : {
'' : function() { /* ... */ } // деструктор экземпляра
}
}
});
Волны инициализации
Инициализация экземпляров блоков и элементов, присутствующих на странице, не обязательно происходит одновременно. Они могут динамически добавляться в ходе работы, инициализироваться по запросу или событию. Инициализация очередной группы блоков или элементов называется волной инициализации.
Новая волна инициализации создается в следующих случаях:
Автоматическая инициализация блоков и элементов по событию
domReady.Явный вызов инициализации на указанном фрагменте DOM-дерева.
Автоматическая инициализация
i-bem.js позволяет автоматически инициализировать блоки и элементы с DOM-представлением в момент наступления DOM-события domReady.
Включить автоматическую инициализацию можно, указав блок i-bem с модификатором init в значении auto в файле зависимостей .deps.js.
Пример файла .deps.js:
({
shouldDeps : [
{
block : 'i-bem',
elem : 'dom',
mods : { init : 'auto' }
}
]
})
Блок page уже содержит в зависимостях i-bem-dom_init_auto, поэтому если он используется в проекте, не требуется ничего дополнительно подключать.
Примечание Блоки и элементы, для которых задекларирована ленивая инициализация, не будут инициализированы автоматически.
Ленивая инициализация
Если на странице размещено много экземпляров блоков и элементов, их автоматическая инициализация в момент загрузки страницы нежелательна, так как она увеличивает время загрузки и объем памяти, затрачиваемой браузером.
Рекомендуется инициализировать блоки и элементы только в тот момент, когда их функциональность потребуется пользователю, например, по клику на блок. Такая инициализация называется ленивой.
Для декларации ленивой инициализации, в декларации зарезервировано статическое свойство lazyInit типа Boolean.
При lazyInit : true, блоки или элемнеты данного класса будут инициализированы только при попытке получить соответствующий экземпляр (см. раздел «Взаимодействие блоков»).
modules.define('my-block', ['i-bem-dom'], function(provide, bemDom) {
provide(bemDom.declBlock(this.name, {
onSetMod : {
'js' : {
'inited' : function() {
// этот код будет выполняться при первом обращении к экземпляру блока
}
}
}
}, {
lazyInit : true
}));
});
Декларация с lazyInit : false позволяет отменить ленивую инициализацию, заданную на другом уровне переопределения.
Примечание Ленивая инициализация может быть отменена для конкретного экземпляра. Для этого нужно указать в параметрах HTML-элемента, к которому привязан экземпляр
data-bem='{ "my-block" : { "lazyInit" : false } }'.
Инициализация класса
В терминах i-bem-dom существует понятие инициализация класса. Она происходит в момент прохождения волны инициализации на HTML-фрагменте, когда в нем впервые за время жизни приложения встречается блок или элемент данного класса.
Инициализация класса необходима для реализации ленивой инициализации по DOM- или БЭМ-событию. Для этого в декларации зарезервирован статический метод onInit, внутри которого можно подписаться на нужные события.
Пример
Блок button будет инициализирован по DOM-событию click на DOM-узле блока.
modules.define('button', ['i-bem-dom'], function(provide, bemDom) {
provide(bemDom.declBlock(this.name, {
onSetMod : {
'js' : {
'inited' : function() {
// выполняется при первом DOM-событии "click"
}
}
},
_onClick: function(e) {
// выполняется при каждом DOM-событии "click"
}
}, {
lazyInit : true,
onInit : function() {
this._domEvents().on(
'click',
this.prototype._onClick); // в момент клика будет создан экземпляр блока и вызван его метод _onClick
}
}));
});
Блок my-form инициализируется по БЭМ-событию click вложенного в него блока button.
modules.define('my-form', ['i-bem-dom', 'button'], function(provide, bemDom, Button) {
provide(bemDom.declBlock(this.name, {
_onButtonClick : function(e, data) {
// функция-обработчик БЭМ-события click на вложенных блоках button
}
}, {
lazyInit : true,
onInit : function() {
this._events(Button).on('click', this.prototype._onButtonClick);
}
}));
});
Примечание Свойства
lazyInitиonInitотносятся к статическим свойствам класса. Поэтому даже если оно задано в декларации блока или элемента с определенным модификатором, они будут применены ко всем экземплярам данного класса, вне зависимости от модификаторов.
Инициализация блоков и элементов на фрагменте DOM-дерева
Процедура инициализации JS-объектов может быть вызвана явно для указанного фрагмента DOM-дерева. Такая необходимость возникает при динамическом обновлении блоков или элементов.
Следующие функции выполняют динамическую инициализацию блоков и элементов:
init(),destruct()– инициализация и уничтожение экземпляров на указанном фрагменте DOM-дерева.update(),replace(),append(),prepend(),before(),after()– обновление фрагмента DOM-дерева с одновременной инициализацией на обновленном фрагменте.
Пример использования функций, выполняющих динамическую инициализацию см. в разделе «Динамическое обновление блоков и элементов в DOM-дереве».
Инициализация и удаление блоков без DOM-представления
Для создания JS-объектов блока или элемента без DOM-представления (не привязанного к HTML-элементу) служит статический метод create() классов Block или Elem из модуля i-bem.
Метод принимает аргументы:
mods{Object}– модификаторы создаваемого блока или элемента.params{Object}– параметры блока или элемента.
Возвращает экземпляр указанного класса.
Удаление экземпляров блоков и элементов без DOM-представления не может быть выполнено автоматически. Блоки и элементы без DOM-представления представляют собой обычные JS-объекты и удаляются в момент удаления всех ссылок на объект.