В основе Backbone.js лежит событийно-ориентированная архитектура,
позволяющая слабо связывать части приложения и управлять взаимодействием
между ними через механизм событий. Центральным элементом этой
архитектуры является объект Backbone.Events, который может
быть примешан к любому объекту и наделяет его возможностью генерировать
и обрабатывать события.
События используются для уведомления о состоянии модели, изменениях коллекций, жизненном цикле представлений и для организации произвольного взаимодействия между компонентами без прямых зависимостей.
Backbone.Events — это набор методов, реализующий паттерн
Observer. Он не является классом, а представляет собой объект с
методами, которые можно примешать (mixin) к любому другому объекту.
Ключевые методы:
on — подписка на событиеoff — отписка от событияtrigger — генерация событияonce — одноразовая подпискаlistenTo — подписка с автоматическим управлением
контекстомstopListening — снятие подписок, созданных через
listenToПримешивание событий:
var obj = {};
_.extend(obj, Backbone.Events);
После этого объект способен участвовать в событийном взаимодействии.
Базовый сценарий работы с событиями заключается в подписке на событие и его последующем вызове.
obj.on('custom:event', function(data) {
console.log(data);
});
obj.trigger('custom:event', { value: 42 });
События идентифицируются строковыми именами. Допускается передача произвольного количества аргументов в обработчик.
Особенности:
По умолчанию this внутри обработчика указывает на
объект, который сгенерировал событие. Контекст можно явно задать третьим
аргументом:
obj.on('event', callback, context);
Контроль контекста критически важен при работе с представлениями и моделями, особенно в сложных приложениях с большим количеством компонентов.
Метод once позволяет подписаться на событие, которое
будет обработано только один раз:
obj.once('init', function() {
console.log('Инициализация завершена');
});
После первого срабатывания обработчик автоматически удаляется. Это полезно для событий жизненного цикла или асинхронных операций.
Методы listenTo и stopListening
предназначены для безопасного управления подписками между объектами.
view.listenTo(model, 'change', view.render);
Преимущества listenTo:
Снятие подписок:
view.stopListening();
Или выборочно:
view.stopListening(model, 'change');
Backbone.Model активно использует события для
уведомления об изменениях состояния.
Основные события модели:
change — любое изменение атрибутовchange:attribute — изменение конкретного атрибутаinvalid — ошибка валидацииdestroy — удаление моделиПример:
model.on('change:title', function(model, value) {
console.log('Новое значение title:', value);
});
Событие change срабатывает один раз после всех
изменений, даже если было изменено несколько атрибутов.
Backbone.Collection генерирует события при изменении
состава и состояния коллекции.
Основные события:
add — добавление моделиremove — удаление моделиreset — полная замена содержимогоupdate — агрегированное событие измененийsort — изменение порядкаПример обработки:
collection.on('add', function(model) {
console.log('Добавлена модель', model.id);
});
Коллекции также проксируют события моделей, находящихся внутри них, что позволяет отслеживать изменения элементов без прямой подписки на каждую модель.
Backbone.View использует событийную модель в двух
аспектах:
DOM-события описываются через хэш events:
events: {
'click .button': 'onClick'
}
Метод delegateEvents автоматически связывает DOM-события
с методами представления.
Пользовательские события представления используются для коммуникации с внешними компонентами:
this.trigger('view:ready');
Это позволяет отделить логику отображения от бизнес-логики.
Для организации взаимодействия между независимыми частями приложения часто используется глобальный объект-событийник:
var vent = _.extend({}, Backbone.Events);
Такой объект выполняет роль Event Bus:
Пример использования:
vent.on('user:login', function(user) {
console.log('Пользователь вошёл', user.id);
});
Для поддержания читаемости и масштабируемости применяются соглашения по именованию:
model:save,
view:renderuser:create,
order:updateupdate,
doneЧёткая схема именования снижает риск конфликтов и упрощает отладку.
Backbone не навязывает модель асинхронного программирования, но события часто используются для обработки результатов асинхронных операций.
Пример:
model.save(null, {
success: function() {
model.trigger('save:success');
}
});
Событийный подход позволяет отделить обработку результата от инициатора операции.
Несмотря на гибкость, событийная архитектура имеет особенности:
Эти ограничения компенсируются при правильной архитектуре и
использовании listenTo/stopListening.
Event-driven подход в Backbone.js:
События пронизывают все уровни фреймворка — от моделей до представлений — и формируют основу взаимодействия в приложениях, построенных на Backbone.js.