首页 文章

$ on和$ broadcast in angular

提问于
浏览
261

我有一个footerController和codeScannerController具有不同的视图 .

angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);

angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...

当我点击footer.html中的 <li> 时,我应该在codeScannerController中获取此事件 .

<li class="button" ng-click="startScanner()">3</li>

我认为它可以通过 $on$broadcast 实现,但我不能在任何地方找到示例 .

4 回答

  • 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
    });
    

    Scope docs内的文档 .

  • 88

    首先,$on(), $broadcast() and $emit()的简短描述:

    • .$on(name, listener) - 按给定的 name 收听特定事件

    • .$broadcast(name, args) - 通过所有孩子的 $scope 播放一个事件

    • .$emit(name, args) - 将 $scope 层次结构中的事件发送给所有父级,包括 $rootScope

    基于以下HTML(请参阅full example here):

    <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

    • 广播2 - 将被控制器2看到 $scope 然后控制器3 $scope

    • Emit 2 - 将被控制器2看到 $scope 然后 $rootScope

    • 广播3 - 只有控制器3才能看到 $scope

    • Emit 3 - 将被控制器3 $scope ,控制器2 $scope 以及 $rootScope 看到

    • 广播根 - 将由所有控制器的 $rootScope$scope 看到(1,2和3)

    • Emit Root - 只会被 $rootScope 看到

    用于触发事件的JavaScript(再次,您可以看到working example here):

    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');
        });
    }]);
    
  • 26

    你应该知道的一件事是$ prefix指的是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

    我们应该使用哪个? $ broadcast将向下传递给所有孩子的dom元素,$ emit将向所有祖先dom元素传递相反的方向 .

    避免在$ emit或$ broadcast之间做出决定的最佳方法是从$ rootScope进行通道并使用$ broadcast到其所有子节点 . 由于我们的dom元素是兄弟姐妹,这使我们的案例变得更容易 .

    Adding $rootScope and lets $broadcast

    app.controller('FirstCtrl', function($rootScope, $scope){
        $scope.register = function(){
            $rootScope.$broadcast('BOOM!', $scope.name)
        }
    });
    

    注意我们添加了$ rootScope,现在我们使用$ broadcast(broadcastName,arguments) . 对于broadcastName,我们想给它一个唯一的名称,以便我们可以在secondCtrl中捕获该名称 . 我选择了BOOM!纯娱乐 . 第二个参数'arguments'允许我们将值传递给侦听器 .

    Receiving our broadcast

    在我们的第二个控制器中,我们需要设置代码来收听我们的广播

    app.controller('SecondCtrl', function($scope){
      $scope.$on('BOOM!', function(events, args){
        console.log(args);
        $scope.name = args; //now we've registered!
      })
    });
    

    这真的很简单 . Live Example

    Other ways to achieve similar results

    尽量避免使用这套方法,因为它既不高效又不易维护,但它是解决您可能遇到的问题的简单方法 .

    您通常可以通过使用服务或简化控制器来执行相同的操作 . 我们不会详细讨论这个问题,但我认为我只是提到完整性 .

    最后,请记住一个真正有用的广播,再次'$ destroy'可以看到$表示它是供应商代码创建的方法或对象 . 无论如何,当控制器被破坏时,广播会播放$ destroy,你可能想要听听它以了解何时删除你的控制器 .

  • 602
    //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();
           };
        }); }());
    

相关问题