【问题标题】:angular.js $destroy event - should I manually unbind?angular.js $destroy 事件 - 我应该手动解除绑定吗?
【发布时间】:2014-04-05 20:47:17
【问题描述】:

我试图弄清楚当范围销毁时,angular base 是否会自动取消绑定与$scope.$on(...)$scope.$watch(...) 绑定的观察者和范围事件?

假设我有以下代码:

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

当作用域上触发 $destroy 事件时,我是否需要手动取消绑定这些观察者和事件?

【问题讨论】:

  • 这取决于你在哪里设置了$watch,如果它在一个指令中,yes, you do

标签: javascript angularjs angularjs-scope


【解决方案1】:

根据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 事件并自己进行必要的清理

【讨论】:

  • 我知道我需要为 $destroy 事件上的所有非角度绑定手动执行此操作。虽然我错过了关于“...停止参与模型更改检测和侦听器通知...”的部分,但谢谢
  • 抱歉,看完后我还是不明白:$scope.$on 和 $scope.$watch 是自动解除绑定的,还是应该在销毁事件中解除绑定?
  • $scope 上的所有观察者都自动解除绑定。但是,您应该手动取消绑定 $rootScope 和指令内的 DOM 元素上的侦听器。
  • 你会看到一些 Angular 文件(一个是 ng-grid)的模式,其中 Angular 开发人员使用它来取消绑定 $scope 中的 $watch:$scope.$on('$destroy', $scope.$watch('renderedColumns', function() { // do stuff }));,它只是传递了取消 $watch 的函数直接连接到 $destroy 事件监听器。
【解决方案2】:

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

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

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

【讨论】:

  • 你是怎么知道的?我假设您也在为指令中的controller 语法说话?这是否也意味着链接函数中的任何作用域都不会解除绑定?
  • 事实上,这种自动注销通常适用于范围、控制器和指令。这是因为当删除控制器或从 DOM 中删除元素时,会触发销毁事件。此事件取消绑定相关范围内的所有事件。这意味着您必须关心 $rootScope 上添加的事件,因为它永远不会被删除。
  • 你可以在这里阅读一些信息:范围生命周期:docs.angularjs.org/guide/scopedestroy event:docs.angularjs.org/api/ng/type/$rootScope.Scope#$destroydestroy event on elements:docs.angularjs.org/api/ng/function/angular.element
【解决方案3】:

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

需要注意的重要一点是,$rootScope 当然永远不会被销毁,除非您退出您的应用程序。因此,如果您执行$rootScope.$on('someEvents', handleSomeEvent);,您可能必须自己删除该事件,具体取决于您在哪里收听该事件:

  • 如果在controllerdirective 中,则必须手动删除它,否则每次实例化controller 时,都会附加一个新事件,因此handleSomeEvent 将是多次调用
  • 如果在service 中,则无需手动删除它,因为服务始终为singleton(请注意,在Angular 中servicefactory、...最终都是同一个东西)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    相关资源
    最近更新 更多