AngularJS清理和内存泄漏

3

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

如果您在作用域和元素上注册了监听器,则当它们被销毁时,这些监听器将自动清除,但是如果您在服务上注册了监听器或在未删除的DOM节点上注册了监听器,则必须自行清除它们,否则可能会引入内存泄漏。

我有一个疑问(实际上我不理解Angular中的很多东西,但现在我关注的确切问题是这个)。是否可以有人解释一下“在作用域和元素上注册的监听器”与“在服务上注册监听器或在DOM上注册监听器”的区别。在此句中,元素和DOM之间有什么区别。为什么在第一种情况下监听器会自动清除,而在第二种情况下却不会。在元素上注册了什么内容?在DOM上注册了什么内容?

1个回答

4
请注意,这里涉及到两种略微不同的清理方式:
  1. 事件监听函数可能需要清理。
  2. 创建的元素也可能需要清理。
在这些情况下,Angular 会为您进行清理:
// Watching scope vars
$scope.$watch("scopeVariable", function (newVal) { ... });
$scope.$watch("injectedService.serviceVar", function (newVal) { ... } );

// Listening to events from a scope
$scope.$on("event", function () { ... });

// Events of the element of a directive,
// within the directive 'link' function (the docs you referenced)
element.on('click', function() { ... });

在这些情况下,不需要进行任何清理。Angular知道某些代码正在监听事件或监视变量,并能够注销它们。对于该元素,由于它将被移除,所有闭包和相关对象都将被取消引用,因此稍后会被垃圾回收器处理。
另一方面,在以下情况下,Angular不会为您执行清理操作:
// Listening to events from rootScope
$rootScope.$on("event", function () { ... });

// Subscribing to services events
someInjectedService.subscribeIncomingMessage(function () { ... });

// Adding elements outside directive container element
var body = $document.find('body').eq(0);
var newElement = angular.element('<div></div>');
body.append(newElement);

// Listening to events of elements outside your directive (ie. body)
body.on("click", function() { ... });

在这些情况下,Angular 永远不会销毁您的监听器,也不会销毁添加到文档 <body> 的创建元素。
换句话说,Angular 只会销毁您指令根元素作用域内的所有内容或包含在 DOM 中的所有内容。您监听的其他所有内容或在指令外部创建和放置的元素都是您的责任。
引用 Angular 文档的话,您可以通过监听销毁事件来进行清理:
最佳实践:指令应该自我清理。您可以使用 element.on('$destroy', ...)scope.$on('$destroy', ...) 运行清理函数,以便在指令被移除时进行清理。
我个人只在需要清理时才添加这些方法。特别是如果您创建元素或注册外部事件(例如来自 WebSockets 的消息或计划的超时事件),则必须这样做,否则您可能会出现多个监听器监听同一事件(通常会导致错误和缓慢)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接