Backbone.js строится вокруг событийной модели, которая позволяет компонентам приложения взаимодействовать без жёсткой связки друг с другом. Пользовательские события — ключевой механизм для организации обмена сообщениями между моделями, коллекциями, представлениями и любыми другими объектами.
В основе лежит модуль Backbone.Events, который может
быть примешан к любому объекту. Он предоставляет универсальный интерфейс
для регистрации, генерации и управления событиями.
Backbone.Events — это не класс, а набор методов, которые
добавляются объекту через примешивание:
var obj = {};
_.extend(obj, Backbone.Events);
После этого объект получает методы:
onofftriggeroncelistenTostopListeningЭто позволяет использовать событийную модель вне стандартных сущностей Backbone.
Метод on подписывает обработчик на событие:
model.on('custom:event', function(value) {
console.log(value);
});
Особенности:
model.on('change update reset', handler, this);
Событие инициируется методом trigger:
model.trigger('custom:event', 42);
Все аргументы после имени события передаются обработчикам.
Важно: события Backbone являются синхронными. Все подписчики будут вызваны немедленно, в порядке регистрации.
По умолчанию this внутри обработчика указывает на
объект-источник события. Это поведение можно изменить:
model.on('custom:event', handler, view);
В этом случае this внутри handler будет
указывать на view.
once регистрирует обработчик, который будет выполнен
только один раз:
model.once('initialized', function() {
console.log('Сработает один раз');
});
После первого срабатывания обработчик автоматически удаляется.
Метод off удаляет подписки:
model.off('custom:event', handler);
Возможные варианты:
model.off();
Неправильное использование off может привести к
трудноотлавливаемым ошибкам, особенно в больших приложениях.
listenTo решает проблему утечек памяти, когда объекты
подписываются друг на друга:
view.listenTo(model, 'custom:event', viewHandler);
Преимущества:
Удаляет все подписки, созданные через listenTo:
view.stopListening();
Или только для конкретного объекта:
view.stopListening(model);
Это особенно важно в методе remove у
Backbone.View, чтобы корректно освобождать ресурсы.
Модели Backbone уже используют события (change,
sync, destroy), но пользовательские события
расширяют поведение:
var User = Backbone.Model.extend({
login: function() {
this.trigger('user:login', this);
}
});
Такие события позволяют:
Коллекции также поддерживают пользовательские события:
users.trigger('users:loaded', users.length);
Типичные сценарии:
В Backbone.View пользовательские события часто
применяются для внутренней коммуникации:
var View = Backbone.View.extend({
initialize: function() {
this.trigger('view:ready');
}
});
Это позволяет:
Распространённый паттерн — выделение отдельного объекта для глобальных событий:
var EventBus = _.extend({}, Backbone.Events);
Использование:
EventBus.trigger('app:start');
EventBus.on('app:start', handler);
Такой подход:
Рекомендуется использовать пространства имён:
'user:login'
'cart:item:add'
'view:rendered'
Преимущества:
События могут инициировать другие события:
model.on('validated', function() {
model.trigger('ready');
});
Такой подход позволяет строить цепочки обработки, но требует аккуратности, чтобы избежать циклов и неочевидных зависимостей.
Частые проблемы:
Событийная модель облегчает архитектуру, но при неправильном использовании делает поведение системы непрозрачным.
Любой объект может стать источником событий:
function Service() {}
_.extend(Service.prototype, Backbone.Events);
Это позволяет:
Пользовательские события — основной инструмент слабой связанности в
Backbone.js. Они заменяют прямые вызовы методов, обеспечивают
масштабируемость и упрощают тестирование. Грамотное использование
Backbone.Events позволяет строить сложные интерфейсы,
оставаясь в рамках простой и предсказуемой модели.