$on и $broadcast в angular
у меня есть нижний колонтитул и codeScannerController с разными представлениями.
angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);
angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...
когда я нажимаю на <li> в футере.html я должен получить это событие в codeScannerController.
<li class="button" ng-click="startScanner()">3</li>
Я думаю, что это может быть реализовано с $on и $broadcast, но я не знаю как и не могу найти примеры где угодно.
4 ответов:
если вы хотите
$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 });документация для этого внутри объем документов.
во-первых, краткое описание
$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следующим образом:
- Broadcast 1 - будет видно только контроллером 1
$scope- излучение 1-будет видно контроллером 1
$scopeзатем$rootScope- трансляция 2-будет видно контроллером 2
$scopeтогда контроллер 3$scope- излучение 2-будет видно контроллером 2
$scopeзатем$rootScope- трансляция 3 - будет видно только регулятором 3
$scope- излучать 3 - будет видно контроллером 3
$scopeконтроллер 2$scopeзатем$rootScope- Broadcast Root-будет видно по
$rootScopeи$scopeвсех контроллеров (1, 2, затем 3)- испускать корень-будет видно только
$rootScopeJavaScript для запуска событий (опять же, вы можете увидеть рабочий пример здесь):
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'); }); }]);
одна вещь, которую вы должны знать, это $ prefix относится к угловому методу, $$ prefixes относится к угловым методам, которые вы должны избегать использования.
ниже приведен пример шаблона и его контроллеров, мы рассмотрим, как $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
что мы должны использовать? $broadcast будет направляться вниз ко всем дочерним элементам dom, а $emit будет направлять противоположное направление ко всем элементам DOM предка.
лучший способ избежать выбора между $emit или $broadcast-это канал из $rootScope и использовать $broadcast для всех его дочерних элементов. Что делает наше дело намного проще, так как наш дом элементы-это братья и сестры.
добавление $rootScope и позволяет $broadcast
app.controller('FirstCtrl', function($rootScope, $scope){ $scope.register = function(){ $rootScope.$broadcast('BOOM!', $scope.name) } });Примечание мы добавили $rootScope и теперь мы используем $broadcast (broadcastName, аргументы). Для broadcastName мы хотим дать ему уникальное имя, чтобы мы могли поймать это имя в нашем secondCtrl. Я выбрал бум! просто для удовольствия. Второй аргумент "аргументы" позволяет передавать значения слушателям.
прием нашей трансляции
в нашем второй контроллер, нам нужно настроить код для прослушивания нашей трансляции
app.controller('SecondCtrl', function($scope){ $scope.$on('BOOM!', function(events, args){ console.log(args); $scope.name = args; //now we've registered! }) });Это действительно просто. Видео
другие способы достижения подобных результатов
старайтесь избегать использования этого набора методов, поскольку он не является ни эффективным, ни простым в обслуживании, но это простой способ исправить проблемы, которые могут возникнуть.
обычно вы можете сделать то же самое с помощью службы или путем упрощения контроллеров. Мы не буду обсуждать это подробно, но я подумал, что просто упомяну об этом для полноты картины.
наконец, имейте в виду, что действительно полезная трансляция для прослушивания-это "$destroy " снова вы можете увидеть $ означает, что это метод или объект, созданный кодами поставщика. В любом случае $destroy транслируется, когда контроллер уничтожается, вы можете послушать это, чтобы узнать, когда ваш контроллер будет удален.
//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(); }; }); }());
Comments