Как правильно общаться между контроллерами?
В настоящее время я использую ужасную выдумку с участием window
:
function StockSubgroupCtrl($scope, $http) {
$scope.subgroups = [];
$scope.handleSubgroupsLoaded = function(data, status) {
$scope.subgroups = data;
}
$scope.fetch = function(prod_grp) {
$http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
}
window.fetchStockSubgroups = $scope.fetch;
}
function StockGroupCtrl($scope, $http) {
...
$scope.select = function(prod_grp) {
$scope.selectedGroup = prod_grp;
window.fetchStockSubgroups(prod_grp);
}
}
Ответы:
Редактировать : проблема, затронутая в этом ответе, была решена в angular.js версии 1.2.7 .
$broadcast
теперь избегает пузырей над незарегистрированными областями и работает так же быстро, как $ emit.Итак, теперь вы можете:
$broadcast
из$rootScope
$on
местных,$scope
которые должны знать о событииОригинальный ответ ниже
Я настоятельно советую не использовать
$rootScope.$broadcast
+,$scope.$on
а скорее$rootScope.$emit
+$rootScope.$on
. Первое может привести к серьезным проблемам с производительностью, как поднял @numan. Это потому, что событие будет проходить через все области видимости.Однако последний (использующий
$rootScope.$emit
+$rootScope.$on
) от этого не страдает и поэтому может использоваться как канал быстрой связи!Из угловой документации
$emit
:Так как выше нет области видимости
$rootScope
, не происходит никакого пузырения. Абсолютно безопасно использовать$rootScope.$emit()
/$rootScope.$on()
как EventBus.Однако при использовании изнутри контроллеров есть один недостаток. Если вы выполняете прямую привязку к
$rootScope.$on()
контроллеру изнутри, вам придется самостоятельно очищать привязку при$scope
разрушении вашей локальной системы . Это связано с тем, что контроллеры (в отличие от сервисов) могут создаваться несколько раз за время жизни приложения, что приведет к суммированию привязок, что в конечном итоге приведет к утечкам памяти повсюду :)Чтобы отменить регистрацию, просто слушать на вашем
$scope
«S$destroy
события , а затем вызвать функцию , которая вернула$rootScope.$on
.Я бы сказал, что это не совсем конкретная вещь, так как она применима и к другим реализациям EventBus, что вы должны очистить ресурсы.
Тем не менее, вы можете сделать вашу жизнь проще для этих случаев. Например, вы можете установить патч для обезьяны
$rootScope
и дать ему$onRootScope
подписку на события, генерируемые на нем,$rootScope
но также непосредственно очищать обработчик, когда локальный$scope
объект уничтожается.Самый простой способ обезвредить патч
$rootScope
для предоставления такого$onRootScope
метода был бы через декоратор (блок run, вероятно, тоже отлично это сделает, но pssst, никому не говорите)Чтобы убедиться, что
$onRootScope
свойство не отображается неожиданно при перечислении,$scope
мы используемObject.defineProperty()
и устанавливаемenumerable
вfalse
. Имейте в виду, что вам может понадобиться прокладка ES5.С помощью этого метода код контроллера сверху можно упростить до:
В качестве окончательного результата всего этого я настоятельно советую вам использовать
$rootScope.$emit
+$scope.$onRootScope
.Кстати, я пытаюсь убедить команду разработчиков Angular решить проблему в рамках ядра Angular. Здесь идет обсуждение: https://github.com/angular/angular.js/issues/4574
Вот jsperf, который показывает, сколько перфектного воздействия
$broadcast
приносит на стол при достойном сценарии всего за 100$scope
с.http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
источник
Верх ответ здесь был Обойти от Angular проблемы , которая больше не существует (по крайней мере , в версии> 1.2.16 и «вероятно , раньше») , как @zumalifeguard упомянул. Но я остался читать все эти ответы без фактического решения.
Мне кажется, что ответ сейчас должен быть
$broadcast
из$rootScope
$on
местных,$scope
которые должны знать о событииТак что опубликовать
И подписаться
Plunkers
Controller As
синтаксисЕсли зарегистрировать слушатель на локальном
$scope
, он будет уничтожен автоматически$destroy
сам по себе , когда соответствующему контроллеру удаляется.источник
controllerAs
синтаксисом? Я мог использовать$rootScope
подписчика для прослушивания события, но мне было просто любопытно, был ли другой образец.$scope
явно. Джон Папа пишет о событиях быть один «исключением» к своему обычному правилу учета$scope
«из» своих контроллеров (я использую кавычки , потому что , как он упоминает доController As
сих пор$scope
, это только под капотом).controller as
синтаксической альтернативы по запросу. Я надеюсь, это то, что вы имели в виду.Использование $ rootScope. $ Broadcast и $ scope. $ On для связи PubSub.
Также смотрите этот пост: AngularJS - Связь между контроллерами
источник
$rootScope
и$watch
. Не уверен, что это улучшение.Поскольку у defineProperty есть проблема совместимости браузера, я думаю, что мы можем подумать об использовании сервиса.
и использовать его в контроллере следующим образом:
контроллер 1
контроллер 2
источник
GridLinked опубликовал решение PubSub, которое, кажется, разработано довольно хорошо. Услугу можно найти здесь .
Также схема их обслуживания:
источник
На самом деле использование emit и broadcast неэффективно, потому что событие всплывает вверх и вниз по иерархии областей действия, что может легко перерасти в снижение производительности для сложного приложения.
Я бы предложил воспользоваться услугой. Вот как я недавно реализовал это в одном из моих проектов - https://gist.github.com/3384419 .
Основная идея - зарегистрировать pubsub / event bus как сервис. Затем внедрите этот eventbus туда, где вам нужно подписаться или опубликовать события / темы.
источник
$rootScope.$emit()
только пузырьки вверх. Тем не менее, так как нет никаких оснований,$rootScope
бояться нечего. Так что, если вы просто используете,$rootScope.$emit()
и у$rootScope.$on()
вас будет быстрый системный EventBus.$rootScope.$on()
внутри своего контроллера, вам нужно будет очистить привязку события, иначе они будут суммироваться, поскольку при каждом создании экземпляра контроллера создается новое, а они - нет. получить автоматически уничтожены для вас, так как вы привязаны к$rootScope
напрямую.Используя методы get и set внутри службы, вы можете очень легко передавать сообщения между контроллерами.
в HTML HTML вы можете проверить, как это
источник
Что касается исходного кода - кажется, вы хотите поделиться данными между областями. Чтобы поделиться данными или состоянием между $ scope, документы предлагают использовать сервис:
Ссылка: угловые документы ссылка здесь
источник
Я фактически начал использовать Postal.js в качестве шины сообщений между контроллерами.
В этом есть много преимуществ, таких как шина сообщений, такая как привязки в стиле AMQP, способ, которым почтовые службы могут интегрировать w / iFrames и веб-сокеты, и многое другое.
Я использовал декоратор, чтобы настроить Почту на
$scope.$bus
...Вот ссылка на сообщение в блоге по этой теме ...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/
источник
Вот как я это делаю с Factory / Services и простым внедрением зависимостей (DI) .
источник
Мне понравился способ, которым
$rootscope.emit
был использован для достижения взаимосвязи. Я предлагаю чистое и эффективное решение, не загрязняя глобальное пространство.источник
Вот быстрый и грязный способ.
Вот пример функции, которую нужно добавить в любой из контроллеров одного уровня:
и, конечно, вот ваш HTML:
источник
$rootScope
?Начиная с версии Angular 1.5 и ее компонентной направленности разработки. Рекомендуемый способ взаимодействия компонентов - использование свойства require и привязки свойств (вход / выход).
Компоненту потребуется другой компонент (например, корневой компонент) и получить ссылку на его контроллер:
Затем вы можете использовать методы корневого компонента в вашем дочернем компоненте:
Это функция контроллера корневого компонента:
Вот полный архитектурный обзор: связь компонентов
источник
Вы можете получить доступ к этой функции привет в любом месте модуля
Контроллер один
второй контроллер
Больше информации здесь
источник
Я создам сервис и буду использовать уведомления.
Поскольку в любой момент служба уведомлений является одноуровневой, она должна иметь возможность предоставлять постоянные данные.
Надеюсь это поможет
источник
Вы можете использовать встроенную службу AngularJS
$rootScope
и внедрить эту службу в оба ваших контроллера. Затем вы можете прослушивать события, которые запускаются на объекте $ rootScope.$ rootScope предоставляет два вызываемых
$emit and $broadcast
диспетчера событий, которые отвечают за диспетчеризацию событий (могут быть пользовательскими событиями) и используют$rootScope.$on
функцию для добавления прослушивателя событий.источник
Вы должны использовать Сервис, потому что
$rootscope
это доступ из всего Приложения, и это увеличивает нагрузку, или вы можете использовать rootparams, если ваши данные не больше.источник
источник
Вы можете сделать это с помощью угловых событий $ emit и $ broadcast. Насколько нам известно, это лучший, эффективный и действенный способ.
Сначала мы вызываем функцию из одного контроллера.
Вы также можете использовать $ rootScope вместо $ scope. Используйте свой контроллер соответственно.
источник