angular.js $ destroy事件 - 我应该手动取消绑定吗?

时间:2014-03-04 10:52:23

标签: javascript angularjs angularjs-scope

我正在尝试确定当范围销毁时,角度基数是否会自动取消绑定与$scope.$on(...)$scope.$watch(...)绑定的观察者和范围事件?

假设我有以下代码:

$scope.$on('someEvents', handleSomeEvent);
$scope.$watch('someProperty', handleSomePropertyChange);

在范围内触发$ destroy事件时,是否需要手动取消绑定这些观察者和事件?

3 个答案:

答案 0 :(得分:30)

根据Angular documentation on $scope

  当需要将作用域及其子作用域与父作用域永久分离并因此通过调用停止参与模型更改检测和侦听器通知时,必须在作用域上调用$ destroy()'。

另外

  

删除还意味着当前范围符合垃圾回收的条件。

因此,当$destroy()被调用时,所有观察者和听众都被删除,而代表范围的对象变为eligible for garbage collection

如果我们查看destroy() source code,我们会看到一行:

forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));

应该删除所有侦听器。

如@glepretre所述,它适用于控制器中的观察者和监听者。上面列出的相同文档页面表示:

  

请注意,在AngularJS中,还有一个$ destroy jQuery事件,可以在从DOM中删除元素之前清除DOM绑定。

因此,如果指令中有特定的侦听器,您应该听取$destroy事件并自行进行必要的清理

答案 1 :(得分:11)

如果示波器在控制器中,则为您取消角度取消绑定。否则,您可以通过调用返回的函数来取消绑定事件:

var myevent = $scope.$on('someEvents', handleSomeEvent);
myevent() ; // unbind the event

http://docs.angularjs.org/api/ng/function/angular.bind

答案 2 :(得分:5)

如前所述,Angular确实会尽可能地为您清理物品。因此,如果您执行$scope.$on('someEvents', handleSomeEvent);,一旦范围被销毁(例如,当您转到应用中的其他页面/视图时),该事件将自动删除。

值得注意的一点是,除非您退出应用,否则$rootScope当然永远不会被销毁。因此,如果您执行$rootScope.$on('someEvents', handleSomeEvent);,则可能必须自行删除活动,具体取决于您在何处收听活动:

  • 如果在controllerdirective中,则您必须手动删除它,否则每次您实例化controller时,都会附加一个新事件,并且所以handleSomeEvent会被多次调用
  • 如果在service中,则您无需手动删除,因为服务始终为singleton(请注意,在Angular service中,factory,...最终都是同样的事情)