$ on и $broadcast в angular
У меня есть footerController и codeScannerController с разными представлениями.
angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);
angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...
Когда я нажимаю на <li>
в footer.html, я должен получить это событие в codeScannerController.
<li class="button" ng-click="startScanner()">3</li>
Я думаю, что это можно реализовать с помощью $on
и $broadcast
, но я не знаю, как и чего не найти в любом месте.
Ответы
Ответ 1
Если вы хотите $broadcast
использовать $rootScope
:
$scope.startScanner = function() {
$rootScope.$broadcast('scanner-started');
}
Затем, чтобы получить, используйте $scope
вашего контроллера:
$scope.$on('scanner-started', function(event, args) {
// do what you want to do
});
Если вы хотите, вы можете передавать аргументы, когда вы $broadcast
:
$rootScope.$broadcast('scanner-started', { any: {} });
И затем получите их:
$scope.$on('scanner-started', function(event, args) {
var anyThing = args.any;
// do what you want to do
});
Документация для этого внутри Документов области.
Ответ 2
Сначала короткое описание $on()
, $broadcast()
и $emit()
:
-
.$on(name, listener)
- Слушает конкретное событие с помощью данного name
-
.$broadcast(name, args)
- трансляция события через $scope
всех детей
-
.$emit(name, args)
- Вывести событие в иерархию $scope
всем родителям, включая $rootScope
На основе следующего HTML (см. полный пример здесь):
<div ng-controller="Controller1">
<button ng-click="broadcast()">Broadcast 1</button>
<button ng-click="emit()">Emit 1</button>
</div>
<div ng-controller="Controller2">
<button ng-click="broadcast()">Broadcast 2</button>
<button ng-click="emit()">Emit 2</button>
<div ng-controller="Controller3">
<button ng-click="broadcast()">Broadcast 3</button>
<button ng-click="emit()">Emit 3</button>
<br>
<button ng-click="broadcastRoot()">Broadcast Root</button>
<button ng-click="emitRoot()">Emit Root</button>
</div>
</div>
Запущенные события пройдут $scopes
следующим образом:
- Трансляция 1 - будет видна только контроллеру 1
$scope
- Emit 1 - будет отображаться контроллером 1
$scope
, затем $rootScope
- Broadcast 2 - будет отображаться контроллером 2
$scope
, тогда контроллер 3 $scope
- Emit 2 - будет отображаться контроллером 2
$scope
, затем $rootScope
- Трансляция 3 - будет видна только контроллеру 3
$scope
- Emit 3 - будет отображаться контроллером 3
$scope
, контроллер 2 $scope
, затем $rootScope
- Broadcast Root - будет отображаться
$rootScope
и $scope
всех контроллеров (1, 2, затем 3)
- Emit Root - будет видна только
$rootScope
JavaScript для запуска событий (опять же, вы можете увидеть рабочий пример здесь):
app.controller('Controller1', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.broadcastAndEmit = function(){
// This will be seen by Controller 1 $scope and all children $scopes
$scope.$broadcast('eventX', {data: '$scope.broadcast'});
// Because this event is fired as an emit (goes up) on the $rootScope,
// only the $rootScope will see it
$rootScope.$emit('eventX', {data: '$rootScope.emit'});
};
$scope.emit = function(){
// Controller 1 $scope, and all parent $scopes (including $rootScope)
// will see this event
$scope.$emit('eventX', {data: '$scope.emit'});
};
$scope.$on('eventX', function(ev, args){
console.log('eventX found on Controller1 $scope');
});
$rootScope.$on('eventX', function(ev, args){
console.log('eventX found on $rootScope');
});
}]);
Ответ 3
Одна вещь, которую вы должны знать, это префикс $относится к Angular методу, $$ префиксы относятся к Angular методам, которые следует избегать.
ниже приведен пример шаблона и его контроллеров, мы рассмотрим, как $broadcast/$on может помочь нам достичь желаемого.
<div ng-controller="FirstCtrl">
<input ng-model="name"/>
<button ng-click="register()">Register </button>
</div>
<div ng-controller="SecondCtrl">
Registered Name: <input ng-model="name"/>
</div>
Контроллеры
app.controller('FirstCtrl', function($scope){
$scope.register = function(){
}
});
app.controller('SecondCtrl', function($scope){
});
Мой вопрос к вам в том, как вы передаете имя второму контроллеру, когда пользователь нажимает регистр? Вы можете придумать несколько решений, но тот, который мы собираемся использовать, использует $broadcast и $on.
$broadcast vs $emit
Что мы должны использовать? $будет передаваться всем дочерним элементам, а $emit направит противоположное направление всем элементам предка dom.
Лучший способ избежать выбора между $emit или $broadcast - это канал из $rootScope и использовать $broadcast для всех своих детей. Это делает наш случай намного проще, поскольку наши элементы dom являются братьями и сестрами.
Добавление $rootScope и разрешение $broadcast
app.controller('FirstCtrl', function($rootScope, $scope){
$scope.register = function(){
$rootScope.$broadcast('BOOM!', $scope.name)
}
});
Заметьте, мы добавили $rootScope, и теперь мы используем $broadcast (broadcastName, arguments). Для broadcastName мы хотим дать ему уникальное имя, чтобы мы могли поймать это имя в нашем secondCtrl. Я выбрал BOOM! просто для удовольствия. Аргументы второго аргумента позволяют нам передавать значения слушателям.
Получение нашей широковещательной рассылки
В нашем втором контроллере нам нужно настроить код для прослушивания нашей трансляции
app.controller('SecondCtrl', function($scope){
$scope.$on('BOOM!', function(events, args){
console.log(args);
$scope.name = args; //now we've registered!
})
});
Это действительно так просто. Пример Live
Другие способы достижения аналогичных результатов
Попытайтесь избежать использования этого набора методов, поскольку он не является ни эффективным, ни легким в обслуживании, но это простой способ исправить проблемы, которые могут возникнуть.
Обычно вы можете делать то же самое, используя сервис или упрощая свои контроллеры. Мы не будем обсуждать это подробно, но я думал, что просто упомянул об этом для полноты.
Наконец, имейте в виду, что действительно полезная передача для прослушивания - это "$ destroy" снова, вы можете видеть, что $означает, что это метод или объект, созданный кодами поставщика. Anyways $destroy передается, когда контроллер уничтожается, вы можете слушать это, чтобы узнать, когда ваш контроллер удален.
Ответ 4
//Your broadcast in service
(function () {
angular.module('appModule').factory('AppService', function ($rootScope, $timeout) {
function refreshData() {
$timeout(function() {
$rootScope.$broadcast('refreshData');
}, 0, true);
}
return {
RefreshData: refreshData
};
}); }());
//Controller Implementation
(function () {
angular.module('appModule').controller('AppController', function ($rootScope, $scope, $timeout, AppService) {
//Removes Listeners before adding them
//This line will solve the problem for multiple broadcast call
$scope.$$listeners['refreshData'] = [];
$scope.$on('refreshData', function() {
$scope.showData();
});
$scope.onSaveDataComplete = function() {
AppService.RefreshData();
};
}); }());