如何在AngularJS中将广播事件注销到rootscope?

时间:2013-09-17 17:36:45

标签: angularjs

我有以下内容:

angular.module('test')
    .controller('QuestionsStatusController1',
    ['$rootScope', '$scope', '$resource', '$state',
    function ($rootScope, $scope, $resource, $state) {

        $scope.action2 = function() {
            $rootScope.$broadcast('action2@QuestionStatusController1');
        }

    }]);

angular.module('test')
   .controller('QuestionsStatusController2',
   ['$rootScope', '$scope', '$resource', '$state',
   function ($rootScope, $scope, $resource, $state) {

    $rootScope.$on('action2@QuestionStatusController1', function {
         //write your listener here
    })

   }]);

我的理解是我需要取消注册听取事件。有人可以告诉我如何编码/执行此操作吗?

4 个答案:

答案 0 :(得分:149)

如果您没有取消注册该事件,您将收到内存泄漏,因为您传递给$on的函数将无法清除(因为它的引用仍然存在)。更重要的是,任何在其范围内起作用引用的变量也将被泄露。如果在应用程序中多次创建/销毁控制器,这将导致您的函数被多次调用。幸运的是,AngularJS提供了一些有用的方法来避免内存泄漏和不必要的行为:

  • $on方法返回一个函数,可以调用该函数取消注册事件监听器。您需要将取消注册功能保存为变量以供日后使用:var cleanUpFunc = $scope.$on('yourevent', ...);请参阅$on的文档:http://docs.angularjs.org/api/ng.$rootScope.Scope#$on

  • 每当在Angular中清理一个作用域(即控制器被破坏)时,就会在该作用域上触发$destroy事件。您可以注册$scope的{​​{1}}活动,然后通过该活动致电$destroy

您可以将这两个有用的东西绑在一起,以便正确清理您的订阅。我把这个例子放在一起:http://plnkr.co/edit/HGK9W0VJGip6fhYQQBCg?p=preview。如果您注释掉行cleanUpFunc,然后点击切换按钮并执行填充按钮几次,您会注意到我们的事件处理程序被多次调用,这是不太理想的。

现在,在完成所有这些后,为了使您的具体情况正常,只需将cleanUpFunc();中的代码更改为以下内容:

QuestionsStatusController2

通过调用angular.module('test') .controller('QuestionsStatusController2', ['$rootScope', '$scope', '$resource', '$state', function ($rootScope, $scope, $resource, $state) { var cleanUpFunc = $rootScope.$on('action2@QuestionStatusController1', function { //write your listener here }); $scope.$on('$destroy', function() { cleanUpFunc(); }); }]); 中的cleanUpFunc()$destroy事件的事件监听器将被取消订阅,当您的控制器被清理时,您将不再泄漏内存。

答案 1 :(得分:41)

在删除控制器时,在本地$scope上注册侦听器,而不是$rootScopelistener will be destroyed automatically

所以要发布

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

}]);

Plunker

答案 2 :(得分:15)

以下是关于注销逻辑的source code。你可以这样做:

$rootScope.$on('action2@QuestionStatusController1', function () {
    $rootScope.$$listeners['action2@QuestionStatusController1'] = [];
})

或调用从$on()

返回的注销功能
var deregistration = $rootScope.$on('action2@QuestionStatusController1', function () {
    deregistration();
})

答案 3 :(得分:0)

$scope.$on('saveCancelLeadInfo', function (event, args) {

        if ($scope.$$listenerCount["saveCancelLeadInfo"] > 1) {

            $scope.$$listenerCount["saveCancelLeadInfo"] = 0;

        } });