Блог разработчика 1С-Битрикс

Обработка событий в 1С-Битрикс: руководство по BX.bind

В стандартном JavaScript вы, вероятно, привыкли к addEventListener.

В «1С-Битрикс» та же задача решается «платформенным» способом — через BX.bind. Это даёт единый API, совместимый со старыми браузерами, интегрированный с остальными утилитами ядра Bitrix и удобный для отладки. Функция подключена во всех шаблонах ядра, поэтому никакие дополнительные файлы включать не нужно.

Обработка событий. BX.bind

2. Сигнатура и параметры

void BX.bind(
    Object|DOMNode el, // элемент или его id-строка
    String event, // имя события (click, mouseover, bxchange …)
    Function handler // callback-функция
);
  • el — сам DOM-элемент или строка-id. Если передана строка, внутри вызывается BX(el) — аналог document.getElementById.
  • event — строка с именем события. Принимает как нативные (click, keyup …), так и специальные события Bitrix.
  • handler — функция-обработчик.

Важно: создатели платформы рекомендуют оборачивать обработчик в BX.delegate/BX.proxy. Так вы сможете легко удалить слушатель через BX.unbind и повторно использовать одну функцию для многих элементов.


3. Базовые примеры

3.1. Клик по кнопке

<button id="btn-alert">Нажми меня</button>
<script>
BX.bind('btn-alert', 'click', function () {
    alert('Привет из BX.bind!');
});
</script>

3.2. Использование контекста через BX.delegate

<ul id="product-list">
    <li data-id="101">Товар #101</li>
    <li data-id="102">Товар #102</li>
</ul>
<script>
var App = {
    handleProductClick: function (e) {
        // BX.proxy_context всегда указывает на реальный элемент, вызвавший событие
        var id = BX.proxy_context.getAttribute('data-id');
        console.log('Товар выбран:', id);
    }
};
BX.bind('product-list', 'click',
    BX.delegate(App.handleProductClick, App)
);
</script>

BX.proxy_context экономит время — не нужно вычислять e.target.


4. Делегирование через BX.bindDelegate

Если список элементов динамический (добавляется позже), вместо того, чтобы перевешивать события, привяжитесь к «контейнеру» раз и навсегда:

<table id="orders">
    <tr data-order="501"><td>501</td><td><a class="delete" href="#">Удалить</a></td></tr>
</table>
<script>
BX.bindDelegate(
    BX('orders'), // узел-контейнер
    'click', // событие
    {className: 'delete'}, // фильтр цели
    function () {
        var row = BX.proxy_context.closest('tr');
        console.log('Удаляем заказ', row.dataset.order);
        BX.remove(row);
    }
);
</script>

Добавьте строку в таблицу хоть через AJAX — обработчик уже там.


5. Специальное событие bxchange

bxchange — «сборное» событие, которое реагирует на change, cut, paste, drop, keyup. Полезно для «живых» форм:

<input id="search" placeholder="Поиск…">
<script>
BX.bind('search', 'bxchange', BX.debounce(function () {
    console.log('Запрос для поиска:', this.value);
}, 300));
</script>

Функция BX.debounce (если подключён модуль main.core) задержит вызов до тех пор, пока пользователь не перестанет вводить текст хотя бы 300 мс.


6. Открепление и уборка

function logResize() { console.log('resize'); }
// подвесили
BX.bind(window, 'resize', logResize);
// … когда больше не нужно
BX.unbind(window, 'resize', logResize);
// или BX.unbindAll(window); // уберёт все события с объекта

Используйте это при переходе между страницами SPA или разрушении Vue/React-компонентов, чтобы избежать утечек памяти.


7. Типичные ошибки и их исправления

Ошибка Как проявляется Как исправить
Передали строку-id, но элемента ещё нет. Событие не срабатывает. Поместите BX.bind внутрь BX.ready или в конец body.
Опечатка в имени метода. В консоли «_hadleMoreButtonClickHandler is not a function_». Пишите правильно: _handleMoreButtonClickHandler.
Забыли снять слушатель. Рост потребления памяти, дублирование вызовов. Всегда храните ссылку на обработчик и вызывайте BX.unbind.
Использовали анонимную функцию без delegate. Нельзя снять обработчик. Оборачивайте через BX.delegate или выносите в именованную функцию.

8. Крупный пример: динамическая корзина

<div id="basket">
    <button class="add" data-id="201">Добавить товар 201</button>
    <button class="add" data-id="202">Добавить товар 202</button>
    <hr>
    <ul id="basket-items"></ul>
</div>
<script>
var Basket = {
    items: {},
    add: function (id) {
        if (!this.items[id]) {
            this.items[id] = 1;
            this.render();
        } else {
            this.items[id] += 1;
            this.updateRow(id);
        }
    },
    render: function () {
        var ul = BX('basket-items');
        ul.innerHTML = '';
        for (var id in this.items) {
            ul.innerHTML += '<li data-id="'+id+'">Товар '+id+
                ' <strong>'+this.items[id]+'</strong> шт. <a href="#" class="del">x</a></li>';
        }
    },
    updateRow: function (id) {
        var row = BX.findChild(BX('basket-items'), {attribute: {'data-id': id}}, true);
        if (row) {
            BX.findChild(row, {tag: 'strong'}, true).textContent = this.items[id];
        }
    },
    remove: function (id) {
        delete this.items[id];
        this.render();
    }
};
// делегируем клики по кнопкам «добавить»
BX.bindDelegate(BX('basket'), 'click', {className: 'add'},
    BX.delegate(function () {
        this.add(BX.proxy_context.getAttribute('data-id'));
    }, Basket)
);
// делегируем клики по ссылкам «удалить»
BX.bindDelegate('basket-items', 'click', {className: 'del'},
    BX.delegate(function () {
        this.remove(BX.proxy_context.parentNode.getAttribute('data-id'));
    }, Basket)
);
</script>

В результате:

  • Нет «лейка» из обработчиков — по два делегированных слушателя на весь блок.
  • Корзина обновляется мгновенно, без перезагрузки страницы.
  • Код легко расширить (добавить счётчик итоговой суммы, отправку AJAX-запроса и т.д.).

9. Чек-лист перед публикацией

  1. Все обработчики обёрнуты в BX.delegate?
  2. Сняты ли слушатели в сценариях одностраничных приложений?
  3. Учитываете ли вы bxchange для текстовых полей?
  4. Нет ли анонимных функций, которые невозможно отвязать?
  5. Названия методов и переменных без опечаток?

10. Заключение

BX.bind — инструмент фронтенд-разработчика на «1С-Битрикс». Освоив его (и парочку спутников — BX.delegate, BX.bindDelegate, BX.unbind), вы избавите свои проекты от избыточного кода, улучшите производительность и сделаете логику событий предсказуемой.

Применяйте паттерны делегирования, не забывайте об уборке слушателей и пишите код, который приятно читать не только поисковым роботам, но и коллегам-разработчикам. Успехов в ваших проектах!

Теги:  BX.bind, обработка событий, JavaScript, BX.delegate, BX.bindDelegate, BX.unbind, веб-разработка


Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Разработка корпоративного сайта

от 7 дней

от 40 000 рублей

Разработка сайта без системы оплаты заказов через корзину

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Лечение сайтов от вирусов

восстановление сайта и подъем версии PHP

от 25 000 рублей
Лечение сайтов на решениях АСПРО и прочих.

* полный комплекс лечения проекта и закрытия дыр

Перенос сайтов на «1С-Битрикс»

сайты на платформе «1С-Битрикс» — это удобство, надежность и высокая посещаемость

от 12 000 рублей
Перенос сайтов с любых CMS и статичных страниц на платформу «1С-Битрикс», с учетом дизайна, верстки и урл-адресов. С сохранением всей информации и структуры сайта.

* зависит от объема выполняемых работ.