Angular 控制器生命周期和事件处理
Posted
技术标签:
【中文标题】Angular 控制器生命周期和事件处理【英文标题】:Angular controller lifetime and event handling 【发布时间】:2016-11-05 09:28:55 【问题描述】:如何正确处理 Angular 控制器中的事件(如$rootScope
或套接字事件)?我面临的问题是我的控制器没有被销毁,这在监听特定事件时会导致一些问题。
为了明确我的意思,这里是一个笨蛋:http://plnkr.co/edit/CkXKUnpUdsbnZEjq8zLy?p=preview
首先触发 rootscope 事件(通过单击按钮)按预期工作:只获取一个事件。但是导航到Route 2
并再次触发 rootscope 事件显示了我的问题;该事件被获取了两次,因为(至少这是我的猜测)两个控制器现在都处于活动状态。每个路由切换都会导致一个额外的事件监听器。
如何处理?
【问题讨论】:
【参考方案1】:使用$scope.$on
而不是$rootScope.$on
,监听器会在作用域销毁时自动销毁。
【讨论】:
好的,这很有帮助,谢谢。只剩下一个问题:这是否意味着像套接字事件(socket.on('event',...)
)这样的事情需要放在服务中而不是控制器中?由于监听套接字事件的行为与监听$rootScope
事件的行为相同,并且可以多次触发。【参考方案2】:
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 (***) 中所述的侦听器删除
另一个可能有用的提示:如果您正在侦听来自 AngularJS 上下文之外的事件(这适用于例如 DOM 事件,但当然也适用于 socket.io 事件),您必须将它们包装在 $ scope.$apply 否则 AngularJS 将不知道事件监听器带来的任何变化。
socket.on('someSocketEvent', function(data)
$scope.$apply(function()
$scope.dataFromSocket = data;
);
);
【讨论】:
以上是关于Angular 控制器生命周期和事件处理的主要内容,如果未能解决你的问题,请参考以下文章
如何在Angular中销毁Nativescript生命周期的applicationOn事件
Ionic 4 迁移:Ionic 3 生命周期事件/导航守卫的 Angular 等价物是啥?