Передача объекта между контроллерами через $emit и $on в AngularJS
Быстрый ответ
В AngularJS для обеспечения коммуникации между контроллерами используются $scope.$emit
и $scope.$on
. Для инициации события используйте $scope.$emit
, а для обработки этого события — $scope.$on
. У вас получится, что события будут отправляться вверх по иерархии областей видимости при помощи $scope.$emit
, а затем их можно будет получать через $scope.$on
. Взгляните на пример:
// В контексте дочернего контроллера
$scope.$emit('event', { data: 'Вверх!' });
// В контексте родительского контроллера
$scope.$on('event', function(event, args) {
console.log(args.data); // Выведет 'Вверх!'
});
Важно: Обязательно отмените подписку на события с помощью функции, которую возвращает $scope.$on
, когда область видимости уничтожается:
var offEvent = $scope.$on('event', function(event, args) { /* ... */ });
$scope.$on('$destroy', offEvent);
[AsideBanner]
$rootScope
: Когда контроллеры не связаны
Если контроллеры между собой не связаны (т.е., они не находятся в иерархии родитель-потомок), можно использовать $rootScope
. Методы $rootScope.$broadcast
или $rootScope.$emit
позволяют инициировать события.
// Контроллеры, нет связи между ними
$rootScope.$broadcast('globalEvent', { data: 'Оповещаем глобально!' });
// Другой контроллер, прослушивающий глобальные события
$rootScope.$on('globalEvent', function(event, args) {
console.log(args.data); // Выведет 'Оповещаем глобально!'
});
Эффективное использование сервиса
Чтобы избежать медленной передачи данных между контроллерами, лучше всего использовать сервисы, которые отлично подходят для хранения общих данных.
app.service('SharedService', function() {
var sharedData = {};
return {
setData: function(data) {
sharedData = data;
},
getData: function() {
return sharedData;
}
};
});
Повышение производительности: умное использование событий
Будьте осторожны при использовании $rootScope.$broadcast
, так как это воздействует на все области видимости. Из-за этого может снизиться производительность вашего приложения, поэтому стоит подумать над более оптимальными решениями, такими как услуги или прямые вызовы методов.
Визуализация
Давайте представим, что $scope.$emit и $scope.$on – подобны радиовышке и приемникам:
📡 **Радиовышка** 📡
($scope.$emit)
|
🎵-----------------------------🎵
| | | | | | |
📻 📻 📻 📻 📻 📻 📻
($scope.$on) ($scope.$on) ... ($scope.$on)
Радиовышка 📡 транслирует сигналы:
$scope.$emit('concertName', data); // Концерт начался!
Приёмники 📻 настроены на приём этих сигналов через $scope.$on. Мы просто в восторге!
$scope.$on('concertName', function(event, data) {
// Наслаждаемся концертом
});
События от $scope.$emit распространяются вверх по дереву областей видимости, в то время как события от $broadcast
транслируются вниз, достигая всех уголков приложения.
// Родительский контроллер инициирует событие для дочерних контроллеров
$scope.$broadcast('downEvent', { data: 'Вниз по дереву!' });
Если определенная область видимости уничтожается, все связанные с ней слушатели событий удаляются, но зарегистрированные в $rootScope
следует удалять вручную.
var globalOff = $rootScope.$on('globalEvent', function() {});
$scope.$on('$destroy', function() {
globalOff(); // Чтобы предотвратить утечку памяти
});
Организация событий: простота – залог успешности
Чтобы избежать хаоса среди событий, рекомендуется отправлять через $emit
альтернативные уведомления и позволять родительскому контроллеру правильно их обрабатывать.
Полезные материалы
- Официальная документация AngularJS — подробное описание методов
$emit
,$broadcast
и$on
. - Вопросы по тегам 'angularjs+scope+events' на Stack Overflow — обсуждение и решение проблем, связанных с событиями в AngularJS.
- AngularJS tutorials и курсы на Thinkster — детальное изучение обработки событий и двустороннего связывания данных в AngularJS.
- Учебное видео: Создание погодного приложения на JavaScript — практическое применение JavaScript (особенность: без AngularJS).
- Envato Tuts+ – сериалы о создании стартапов с использованием PHP — персональные идеи для кода и потенциальный источник вдохновения для AngularJS.