Система событий в Backbone реализована через миксин
Backbone.Events и предназначена для организации
слабосвязного взаимодействия между частями приложения. Она решает задачу
оповещения об изменениях состояния без прямых зависимостей между
объектами. Механизм событий используется повсеместно: в моделях,
коллекциях, представлениях и пользовательских объектах.
Backbone.Events — это не класс, а набор методов, которые
могут быть примешаны к любому объекту. Все ключевые компоненты Backbone
уже используют этот миксин, что делает событийную модель единообразной
во всём фреймворке.
Миксин добавляется к объекту через _.extend:
var obj = {};
_.extend(obj, Backbone.Events);
После этого объект получает полный набор методов для работы с событиями. Такой подход позволяет использовать событийную модель вне стандартных компонентов Backbone, например, для создания централизованного event bus.
Метод on используется для подписки на событие:
obj.on('change', function() {
console.log('Событие change сработало');
});
Поддерживаются следующие особенности:
Несколько событий через пробел:
obj.on('add remove', handler);Контекст выполнения:
obj.on('change', handler, this);Контекст особенно важен при работе с представлениями, где обработчик
должен выполняться в контексте экземпляра View.
Метод once регистрирует обработчик, который будет вызван
только один раз:
obj.once('sync', function() {
console.log('Событие sync произошло один раз');
});
После первого срабатывания обработчик автоматически удаляется. Внутренне Backbone оборачивает функцию и отслеживает факт вызова.
Метод trigger инициирует событие и передаёт данные
обработчикам:
obj.trigger('update', 42, { status: 'ok' });
Аргументы передаются в обработчик в том же порядке. Backbone не накладывает ограничений на количество и тип аргументов.
Метод off удаляет обработчики. Возможны разные варианты
использования:
Удаление конкретного обработчика:
obj.off('change', handler);Удаление всех обработчиков события:
obj.off('change');Полная очистка всех событий:
obj.off();Корректное использование off критично для предотвращения
утечек памяти, особенно при динамическом создании и уничтожении
представлений.
Методы listenTo и stopListening
предназначены для управления подписками между объектами с учётом их
жизненного цикла.
this.listenTo(model, 'change', this.render);
Преимущества listenTo:
stopListening(), чтобы снять все
связанные подписки.Пример корректного освобождения ресурсов:
remove: function() {
this.stopListening();
Backbone.View.prototype.remove.call(this);
}
Backbone не поддерживает неймспейсы событий напрямую, но соглашения об именовании позволяют структурировать события:
obj.trigger('user:login');
obj.trigger('user:logout');
Такой подход облегчает чтение кода и снижает риск конфликтов имён.
Событие all срабатывает при любом
trigger:
obj.on('all', function(eventName) {
console.log('Произошло событие:', eventName);
});
Первым аргументом всегда передаётся имя события. Использование
all оправдано для логирования или отладки, но в прикладной
логике требует осторожности из-за потенциального влияния на
производительность.
Backbone.Model активно использует событийную систему.
Наиболее важные события:
Пример:
model.on('change:title', function(model, value) {
console.log('Новое значение title:', value);
});
События change срабатывают только после завершения всех
изменений, что позволяет безопасно реагировать на согласованное
состояние модели.
Backbone.Collection генерирует события при работе с
моделями:
Пример:
collection.on('add', function(model) {
console.log('Добавлена модель', model.id);
});
Коллекция автоматически проксирует события моделей, добавленных в неё, что позволяет отслеживать изменения без ручной подписки на каждую модель.
Backbone.View использует Backbone.Events
для внутренних механизмов и пользовательских сценариев. Часто
применяется в сочетании с DOM-событиями:
events: {
'click .btn': 'onClick'
}
DOM-события и пользовательские события существуют параллельно и не конфликтуют между собой. Представление может генерировать собственные события для внешних компонентов:
this.trigger('submitted', this.model);
Отдельный объект с примешанным Backbone.Events часто
используется как глобальная шина событий:
var vent = _.extend({}, Backbone.Events);
Такой подход позволяет организовать взаимодействие между независимыми модулями без прямых ссылок. Несмотря на удобство, чрезмерное использование глобального event bus усложняет трассировку логики и требует строгих соглашений.
Backbone хранит события во внутреннем объекте _events,
где ключ — имя события, а значение — массив обработчиков. Каждый
обработчик содержит:
once)Эта структура обеспечивает:
off или stopListening при
уничтожении объектов.change вместо
change:attr).Событийная система Backbone проста по API, но требует дисциплины в использовании. При корректной архитектуре она обеспечивает гибкость, масштабируемость и читаемость кода без дополнительных библиотек и сложных паттернов.