Форум

Методологія

Інструментарій

Платформа

Спільнота

Перевод этой статьи на ваш язык отсутствует, вы можете помочь нам перевести.

Инициализация

Инициализация — это создание в памяти браузера 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() { /* ... */ } // деструктор экземпляра
        }
    }
});

Волны инициализации

Инициализация экземпляров блоков и элементов, присутствующих на странице, не обязательно происходит одновременно. Они могут динамически добавляться в ходе работы, инициализироваться по запросу или событию. Инициализация очередной группы блоков или элементов называется волной инициализации.

Новая волна инициализации создается в следующих случаях:

Автоматическая инициализация

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='{ "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-объекты и удаляются в момент удаления всех ссылок на объект.

Якщо ви помітили помилку, або хочете доповнити статтю, ви завжди можете або написати нам про це на Гітхабі, або поправити статтю з допомогою prose.io.