如何正确处理Angular控制器中的事件(如$rootScope
或套接字事件)?我遇到的问题是我的控制器没有被破坏,这在听取特定事件时会引起一些问题。
要清楚我在这里的意思是什么?http://plnkr.co/edit/CkXKUnpUdsbnZEjq8zLy?p=preview
首先触发rootscope事件(通过单击按钮)按预期工作:只提取一个事件。但是导航到Route 2
并再次触发rootcope事件就显示了我的问题;事件被提取两次,因为(至少我的猜测)两个控制器现在都处于活动状态。每个路由开关都会导致一个额外的事件监听器。
如何处理?
答案 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;
});
});