控制器之间的正确通信方式是什么?

我目前正在使用一个可怕的软糖涉及窗口:

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

当前回答

这就是我使用工厂/服务和简单依赖注入(DI)的方法。

myApp = angular.module('myApp', [])

# PeopleService holds the "data".
angular.module('myApp').factory 'PeopleService', ()->
  [
    {name: "Jack"}
  ]

# Controller where PeopleService is injected
angular.module('myApp').controller 'PersonFormCtrl', ['$scope','PeopleService', ($scope, PeopleService)->
  $scope.people = PeopleService
  $scope.person = {} 

  $scope.add = (person)->
    # Simply push some data to service
    PeopleService.push angular.copy(person)
]

# ... and again consume it in another controller somewhere...
angular.module('myApp').controller 'PeopleListCtrl', ['$scope','PeopleService', ($scope, PeopleService)->
  $scope.people = PeopleService
]

其他回答

上面的答案是@zumalifeguard提到的一个Angular问题,这个问题已经不存在了(至少在>1.2.16版本和“可能更早”)。但我读了所有这些答案,却没有一个实际的解决方案。

在我看来,现在的答案应该是

使用$rootScope中的$broadcast 从需要了解事件的本地$作用域使用$on进行监听

所以要发表

// EXAMPLE PUBLISHER
angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope',
function ($rootScope, $scope) {

  $rootScope.$broadcast('topic', 'message');

}]);

和订阅

// EXAMPLE SUBSCRIBER
angular.module('test').controller('ctrlSubscribe', ['$scope',
function ($scope) {

  $scope.$on('topic', function (event, arg) { 
    $scope.receiver = 'got your ' + arg;
  });

}]);

普伦克斯

常规$scope语法(如上所示) new Controller As语法

如果您在本地$作用域上注册了侦听器,当关联的控制器被删除时,它将被$destroy自身自动销毁。

我喜欢$rootscope。使用Emit实现相互通信。我建议清洁和性能有效的解决方案,不污染全球空间。

module.factory("eventBus",function (){
    var obj = {};
    obj.handlers = {};
    obj.registerEvent = function (eventName,handler){
        if(typeof this.handlers[eventName] == 'undefined'){
        this.handlers[eventName] = [];  
    }       
    this.handlers[eventName].push(handler);
    }
    obj.fireEvent = function (eventName,objData){
       if(this.handlers[eventName]){
           for(var i=0;i<this.handlers[eventName].length;i++){
                this.handlers[eventName][i](objData);
           }

       }
    }
    return obj;
})

//Usage:

//In controller 1 write:
eventBus.registerEvent('fakeEvent',handler)
function handler(data){
      alert(data);
}

//In controller 2 write:
eventBus.fireEvent('fakeEvent','fakeData');

你可以通过使用angular事件$emit和$broadcast来实现。据我们所知,这是最好、高效和有效的方法。

首先,我们从一个控制器调用一个函数。

var myApp = angular.module('sample', []);
myApp.controller('firstCtrl', function($scope) {
    $scope.sum = function() {
        $scope.$emit('sumTwoNumber', [1, 2]);
    };
});
myApp.controller('secondCtrl', function($scope) {
    $scope.$on('sumTwoNumber', function(e, data) {
        var sum = 0;
        for (var a = 0; a < data.length; a++) {
            sum = sum + data[a];
        }
        console.log('event working', sum);

    });
});

你也可以用$rootScope代替$scope。相应地使用你的控制器。

实际上,使用emit和broadcast效率很低,因为事件会在作用域层次结构中上下冒泡,这很容易导致复杂应用程序的性能瓶颈。

我建议使用服务。以下是我最近在我的一个项目https://gist.github.com/3384419中实现它的方法。

基本思想——将发布/事件总线注册为服务。然后在需要订阅或发布事件/主题的地方注入事件总线。

这是一个快速而肮脏的方法。

// Add $injector as a parameter for your controller

function myAngularController($scope,$injector){

    $scope.sendorders = function(){

       // now you can use $injector to get the 
       // handle of $rootScope and broadcast to all

       $injector.get('$rootScope').$broadcast('sinkallships');

    };

}

下面是一个可以添加到任何兄弟控制器中的示例函数:

$scope.$on('sinkallships', function() {

    alert('Sink that ship!');                       

});

当然这是你的HTML:

<button ngclick="sendorders()">Sink Enemy Ships</button>