【问题标题】:AngularJS : Removing rootScope listener doesn't workAngularJS:删除 rootScope 侦听器不起作用
【发布时间】:2016-06-16 14:58:59
【问题描述】:

我在控制器中有以下代码:

var deregisterSetPermissions =  $rootScope.$on("setPermissions", function () {
    [... some code used when the user click on a "create account" button...]
});
$scope.$on('$destroy', function() {
    deregisterSetPermissions;
    [... and other listeners are unregistered ...]
}

当我离开页面时,所有监听器都未注册:我可以通过 chrome 开发者控制台看到 $rootScope.$$listeners.setPermissions[] 包含一个值,即 null。

当我返回页面并加载后,$rootScope.$$listeners.setPermissions[0] 包含 null 并且 $rootScope.$$listeners.setPermissions[1] 包含侦听器必须调用的函数。 $rootScope.$$listenerCount.setPermissions 为 1。

但是当我点击“创建帐户”按钮时,“setPermissions”监听器使用的函数被调用了两次! 怎么可能?

这是我尝试过的: 1-检查没有创建名称为“setPermissions”的其他侦听器 2- 作用域被销毁时删除监听器的内容:

$scope.$on('$destroy', function() {
    $rootScope.$$listeners.setPermissions=[];
    $rootScope.$$listenerCount.setPermissions = 0;
});

但在那之后,如果我离开页面并返回 3 次,单击“创建帐户”按钮将导致“setPermissions”-listener-function 被调用 3 次...

很高兴了解为什么监听器的函数被多次调用;如果您有解决方案或想法来帮助我继续下去,我期待着阅读它!

【问题讨论】:

  • 你用尾随括号调用deregisterSetPermissions(),对吧?

标签: javascript angularjs


【解决方案1】:

deregisterSetPermissions 是一个函数。要取消订阅侦听器,您必须调用它。

$scope.$on('$destroy', function() {
    deregisterSetPermissions();
}

一般来说,任何时候你发现自己在 Angular 中使用了以双美元符号 ($$) 开头的函数对象,这意味着你做错了——这是 Angular 对不属于其中的东西的命名约定他们的公共 API!

【讨论】:

    【解决方案2】:

    我从这个问题中找到了一些有用的信息: how to unsubscribe to a broadcast event

    我用来构建一个例子:

    var app = angular.module('app', [])
    
    .controller('AppController', function($rootScope) {
      var appCtrl = this;
    
      $rootScope.manageNumbers = false;
    
      appCtrl.addNumber = function() {
        $rootScope.$broadcast('addNumber');
      };
    })
    
    .controller('NumbersController', function($rootScope, $scope) {
      var numCtrl = this;
    
      numCtrl.numbers = [];
      numCtrl.number = 0;
    
      // Register and set handle
      console.log('Register listener');
      var registerListener = $rootScope.$on('addNumber', addNumber);
      logListenerData();
    
      // Unregister
      $scope.$on('$destroy', function() {
        console.log('Unregister listener');
        registerListener();
        // $rootScope.$$listeners.addNumber.length = 0;
        logListenerData();
      });
    
      function addNumber() {
        numCtrl.numbers.push(numCtrl.number);
        numCtrl.number++;
      }
    
      function logListenerData() {
        console.log('$rootScope.$$listeners');
        console.log($rootScope.$$listeners);
        console.log('$rootScope.$$listenerCount');
        console.log($rootScope.$$listenerCount);
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    
    <body ng-app="app">
      <div ng-controller="AppController as appCtrl">
        <button ng-click="$root.manageNumbers=true;" ng-if="!$root.manageNumbers">
          Start Number Management
        </button>
        <button ng-click="$root.manageNumbers=false;" ng-if="$root.manageNumbers">
          Stop Number Management
        </button>
        <button ng-click="appCtrl.addNumber()">
          Add Number
        </button>
      </div>
      <div ng-controller="NumbersController as numCtrl" ng-if="$root.manageNumbers">
        <p>
          <b>Numbers:</b>
          <span ng-repeat="number in numCtrl.numbers">
            {{ $last ? number : number + ', ' }}
          </span>
        </p>
      </div>
    </body>

    注意一些事情。即使您取消注册一个事件,除非该事件在注册时被触发,否则它会在 $$listeners 中有一个“ghost”空值,但不会显示在 $$listenerCounts 中。但是,通过将长度设置为 0 的注释行,我能够删除这些重影;据我所知,它不会造成任何实际差异。

    【讨论】:

      【解决方案3】:

      我终于找到了问题的根源。 服务中还有一个未销毁的 rootScope 侦听器,它正在发出“setPermissions”消息。因此,我可以尝试所有我想要的,但我看错了地方..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-30
        • 2016-10-10
        • 2018-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        相关资源
        最近更新 更多