我有一个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实现,但我不知道如何实现,也找不到任何地方的例子。


如果你想要$broadcast使用$rootScope:

$scope.startScanner = function() {

    $rootScope.$broadcast('scanner-started');
}

然后要接收,使用控制器的$作用域:

$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文档中的相关文档。


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

有一件事你应该知道,$ prefix指的是一个Angular方法,$$ prefixes指的是你应该避免使用的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元素是兄弟元素。

添加$rootScope并让$broadcast

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

注意,我们添加了$rootScope,现在我们使用$broadcast(broadcastName, arguments)。对于broadcastName,我们希望给它一个唯一的名称,以便在我们的secondCtrl中捕获该名称。我选择了BOOM!只是为了好玩。第二个参数arguments允许我们将值传递给侦听器。

接收我们的广播

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

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

就是这么简单。生活的例子

其他达到类似效果的方法

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

您通常可以通过使用服务或简化控制器来实现相同的功能。我们不会详细讨论这个问题,但为了完整起见,我只想提一下。

最后,记住一个非常有用的广播是'$destroy'你可以再次看到$表示它是由供应商代码创建的方法或对象。不管怎样,$destroy在控制器被销毁时被广播,你可能想要听这个来知道你的控制器什么时候被删除。


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

.$on(name, listener) -通过给定的名称监听特定事件 .$broadcast(name, args) -通过所有子对象的$作用域向下广播事件 .$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>

被触发的事件将遍历$作用域,如下所示:

Broadcast 1 - Will only be seen by Controller 1 $scope Emit 1 - Will be seen by Controller 1 $scope then $rootScope Broadcast 2 - Will be seen by Controller 2 $scope then Controller 3 $scope Emit 2 - Will be seen by Controller 2 $scope then $rootScope Broadcast 3 - Will only be seen by Controller 3 $scope Emit 3 - Will be seen by Controller 3 $scope, Controller 2 $scope then $rootScope Broadcast Root - Will be seen by $rootScope and $scope of all the Controllers (1, 2 then 3) Emit Root - Will only be seen by $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');
    });
}]);