AngularJS - 是否$摧毁移除事件侦听器? [英] AngularJS - Does $destroy remove event listeners?

查看:1776
本文介绍了AngularJS - 是否$摧毁移除事件侦听器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://docs.angularjs.org/guide/directive


  

通过监听此事件,你可以移除事件侦听器可能会导致内存泄漏。登记范围和内容监听器自动清理它们被破坏的时候,但如果你注册一个服务侦听器,或注册未被删除DOM节点上的监听,你必须清理自己或你可能引入内存泄漏。


  
  

最佳实践:指令应该照顾自己清理。您可以使用element.on('$毁灭',...)或范围。在$('$毁灭',...)来运行清理功能时,该指令将被删除。


问:

我有一个 element.on点击(事件) - > 我的指令里:


  1. 当指令被破坏,在那里的 element.on 来保持它被垃圾收集?
  2. 的内存引用
    我应该使用一个处理程序上的 $摧毁发出事件移除事件侦听器
  3. 角文档状态。我是IM pression的下的destroy()删除事件侦听器,这是不是这样?


解决方案

事件侦听器

首先是要明白,有两种事件侦听器中很重要


  1. 通过 $上注册范围的事件监听器

      $范围。在$('anEvent',函数(事件数据){
      ...
    });


  2. 通过连接到元素,例如事件处理程序上绑定

      element.on('点击',功能(事件){
      ...
    });



$范围。$摧毁()

$范围。$摧毁()执行它会删除上通过 $关于注册的所有监听器$范围。

它将不可以删除DOM元素或第二种任何附加的事件处理程序。

这意味着,调用 $范围。$摧毁()手动例如指令的链接功能不会删除通过连接例如处理程序中 element.on ,也不是DOM元素本身。


element.remove()

注意删除是一个jqLit​​e方法(或者,如果jQuery是AngularjS之前加载一个jQuery的方法),而不是提供一个标准的DOM元素对象。

element.remove()执行该元素及其所有儿童将从DOM中删除一起将通过例如<$ C $连接所有事件处理程序C> element.on 。

它将不可以破坏与元素相关联的$范围。

要使它更加混乱也有叫一个jQuery事件 $摧毁。有时与删除元素,或者如果你手动删除它们,则可能需要进行清理时,出现这种情况的第三方的jQuery库时:

  element.on('$破坏',函数(){
  。范围$ destroy()方法;
});


怎么办时,一个指令毁

这取决于如何指令销毁。

一个正常的情况是指令被销毁,因为 NG-视图改变当前视图。当这种情况发生的 NG-视图指令将销毁关联$范围内,断绝一切引用它的父范围,并调用删除()的元素。

这意味着,如果该视图包含在它的连接功能与此指令时,它是由摧毁NG-视图

 范围。在$('anEvent',函数(){
 ...
});element.on('点击',功能(){
 ...
});

这两个事件侦听器将被自动删除。

不过,值得注意的是,这些听众里的code还会导致内存泄漏,例如,如果你已经实现了共同的JS内存泄漏模式的 循环引用

甚至在指令的这种通常情况下被破坏掉了,由于一个视图改变有可能需要手动清理的东西。

例如,如果您已注册的侦听器上的 $ rootScope

  VAR unregisterFn = $ rootScope在$('anEvent',函数(){});范围在$('$毁灭',unregisterFn)。

这是因为 $ rootScope 所需的应用程序生命周期过程中不会被破坏。

也是一样,如果你使用的是其他的pub / sub实现,它不会自动执行必要的清理的时候,如果你的指令传递回调服务范围$被破坏,或

另一种情况是,取消 $间隔 / $超时

  VAR承诺= $间隔(函数(){},1000);(范围。在$('$破坏',功能){
  $ interval.cancel(承诺);
});

如果您的指令将事件处理器当前视图之外的例如元素,你需要手动清理这些行动,以及:

  VAR windowClick =功能(){
   ...
};angular.element(窗口)。在('点击',windowClick);(范围。在$('$破坏',功能){
  angular.element(窗口).off(点击,windowClick);
});

这是由 NG-视图或当指令是由角破坏做什么,比如一些例子 NG-如果

如果您有管理的DOM元素的生命周期等自定义指令它当然会变得更加复杂。

https://docs.angularjs.org/guide/directive

By listening to this event, you can remove event listeners that might cause memory leaks. Listeners registered to scopes and elements are automatically cleaned up when they are destroyed, but if you registered a listener on a service, or registered a listener on a DOM node that isn't being deleted, you'll have to clean it up yourself or you risk introducing a memory leak.

Best Practice: Directives should clean up after themselves. You can use element.on('$destroy', ...) or scope.$on('$destroy', ...) to run a clean-up function when the directive is removed.

Question:

I have a element.on "click", (event) -> inside my directive:

  1. When the directive is destroyed, are there any memory references to the element.on to keep it from being garbage collected?
  2. Angular documentation states that I should use a handler to remove event listeners on the $destroy emitted event. I was under the impression that destroy() removed event listeners, is this not the case?

解决方案

Event listeners

First off it's important to understand that there are two kinds of "event listeners":

  1. Scope event listeners registered via $on:

    $scope.$on('anEvent', function (event, data) {
      ...
    });
    

  2. Event handlers attached to elements via for example on or bind:

    element.on('click', function (event) {
      ...
    });
    


$scope.$destroy()

When $scope.$destroy() is executed it will remove all listeners registered via $on on that $scope.

It will not remove DOM elements or any attached event handlers of the second kind.

This means that calling $scope.$destroy() manually from example within a directive's link function will not remove a handler attached via for example element.on, nor the DOM element itself.


element.remove()

Note that remove is a jqLite method (or a jQuery method if jQuery is loaded before AngularjS) and is not available on a standard DOM Element Object.

When element.remove() is executed that element and all of its children will be removed from the DOM together will all event handlers attached via for example element.on.

It will not destroy the $scope associated with the element.

To make it more confusing there is also a jQuery event called $destroy. Sometimes when working with third-party jQuery libraries that remove elements, or if you remove them manually, you might need to perform clean up when that happens:

element.on('$destroy', function () {
  scope.$destroy();
});


What to do when a directive is "destroyed"

This depends on how the directive is "destroyed".

A normal case is that a directive is destroyed because ng-view changes the current view. When this happens the ng-view directive will destroy the associated $scope, sever all the references to its parent scope and call remove() on the element.

This means that if that view contains a directive with this in its link function when it's destroyed by ng-view:

scope.$on('anEvent', function () {
 ...
});

element.on('click', function () {
 ...
});

Both event listeners will be removed automatically.

However, it's important to note that the code inside these listeners can still cause memory leaks, for example if you have achieved the common JS memory leak pattern circular references.

Even in this normal case of a directive getting destroyed due to a view changing there are things you might need to manually clean up.

For example if you have registered a listener on $rootScope:

var unregisterFn = $rootScope.$on('anEvent', function () {});

scope.$on('$destroy', unregisterFn);

This is needed since $rootScope is never destroyed during the lifetime of the application.

The same goes if you are using another pub/sub implementation that doesn't automatically perform the necessary cleanup when the $scope is destroyed, or if your directive passes callbacks to services.

Another situation would be to cancel $interval/$timeout:

var promise = $interval(function () {}, 1000);

scope.$on('$destroy', function () {
  $interval.cancel(promise);
});

If your directive attaches event handlers to elements for example outside the current view, you need to manually clean those up as well:

var windowClick = function () {
   ...
};

angular.element(window).on('click', windowClick);

scope.$on('$destroy', function () {
  angular.element(window).off('click', windowClick);
});

These were some examples of what to do when directives are "destroyed" by Angular, for example by ng-view or ng-if.

If you have custom directives that manage the lifecycle of DOM elements etc. it will of course get more complex.

这篇关于AngularJS - 是否$摧毁移除事件侦听器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆