Работая над очередным проектом с использованием AngularJS, столкнулся с необходимостью "подружить" контроллеры в приложении между собой. А поскольку приложение асинхронно, "дружить" они будут посредством событий.
Сразу давайте разъясним, что же значит "дружить". Имеется ввиду некая разновидность шаблона "подписчик-издатель", где каждый контроллер может быть как подписчиком, так и издателем.
В качестве шины событий (EventBus) будем использовать $rootScope. Причина в следующем: для генерации события я буду использовать метод $emit (работает немного быстрее, чем $broadcast), поэтому в качестве шины лучше использовать корневой элемент дерева областей видимости, чтобы предотвратить "всплывание" события вверх по дереву, которое может стать причиной проблемы производительности.
Кроме того, поскольку в процессе работы приложения контроллеры могут быть созданы множество раз и в качестве шины планируется использовать глобальный по отношению к контроллеру объект, то при уничтожении контроллера необходимо удалять и его подписки:
var subscription = $rootScope.$on('component.evenName', function () {...});
$scope.$on('$destroy', subscription);
Дабы облегчить себе жизнь в разделе config приложения для $rootScope создадим метод, который будет делать это за нас:
var app = angular.module('MyApp', []);
app.config(['$provide', function ($provide) {
$provide.decorator('$rootScope', ['$delegate', function ($delegate) {
Object.defineProperty($delegate.constructor.prototype, '$eventBusOn', {
value: function(name, listener){
var subscription = $delegate.$on(name, listener);
this.$on('$destroy', subscription);
return subscription;
},
enumerable: false
});
return $delegate;
}]);
}]);
Пример использования:
app.controller('FirstController', ['$rootScope', function ($rootScope) {
$rootScope.emit('FirstController.SaysHello', {message: 'Hello from FirstController'});
}]);
app.controller('SecondController', ['$scope', function ($scope) {
$scope.$eventBusOn('FirstController.SaysHello', function (eventData) {
console.log('SecondController caught event with message: ' + eventData.message);
});
}]);
Комментариев нет:
Отправить комментарий