角度控制器生命周期和事件处理

时间:2016-07-03 15:12:34

标签: javascript angularjs events

如何正确处理Angular控制器中的事件(如$rootScope或套接字事件)?我遇到的问题是我的控制器没有被破坏,这在听取特定事件时会引起一些问题。

要清楚我在这里的意思是什么?http://plnkr.co/edit/CkXKUnpUdsbnZEjq8zLy?p=preview

首先触发rootscope事件(通过单击按钮)按预期工作:只提取一个事件。但是导航到Route 2并再次触发rootcope事件就显示了我的问题;事件被提取两次,因为(至少我的猜测)两个控制器现在都处于活动状态。每个路由开关都会导致一个额外的事件监听器。

如何处理?

2 个答案:

答案 0 :(得分:1)

使用$scope.$on代替$rootScope.$on,侦听器将在范围销毁时自动销毁。

答案 1 :(得分:1)

JosselinTD给出的答案是正确的。如果在$ rootScope上广播了一个事件,那么就可以监听各自控制器的$ scope,因为在触发事件的范围之下的所有范围内触发广播,并且所有其他范围都位于$ rootScope之下的某个位置

如果这不是一个选项,例如因为你想要捕获一个被发射的事件(使用$ emit方法而不是$ broadcast)并且没有通过$ scope,你实际上也可以监听$ rootScope。在这种情况下,你必须确保在你的控制器的范围被销毁时监听器被清理:

var removeListener = $rootScope.$on('yourEvent', function(event) {
  // do what you want here..
});
// remove the listener on $rootScope when $scope is cleaned up
// this makes sure we have no unwanted references..
$scope.$on('$destroy', removeListener);

$ on方法返回一个允许删除由它创建的侦听器的函数。当控制器被销毁时,AngularJS将在$ scope上调用$ destroy事件(例如,因为它的视图被其他东西替换)。

如果您正在侦听控制器中的非角度事件,您还应该使用

$scope.$on('$destroy', function() {
   //TODO: call some clean-up function to remove your event listener
 });

可能是socket io listener removal (stackoverflow)

中描述的侦听器删除

另一个可能有用的提示:如果您正在侦听来自AngularJS上下文之外的事件(适用于例如DOM事件,但也适用于socket.io事件),则必须将它们包装在$中范围。$ apply,因为AngularJS将不会意识到事件监听器带来的任何更改。

socket.on('someSocketEvent', function(data) {
  $scope.$apply(function() {
    $scope.dataFromSocket = data;
  });
});