事件监听器
首先,重要的是要了解有两种“事件侦听器”:
范围事件侦听器通过$on
以下方式注册:
$scope.$on('anEvent', function (event, data) {
...
});
通过例如on
或附加到元素的事件处理程序bind
:
element.on('click', function (event) {
...
});
$ scope。$ destroy()
当$scope.$destroy()
执行时,它将删除通过$on
该$ scope 注册的所有侦听器。
它不会删除DOM元素或任何第二种附加的事件处理程序。
这意味着$scope.$destroy()
从指令的链接函数内的示例中手动调用将不会删除通过example附加的处理程序element.on
,也不会删除DOM元素本身。
element.remove()
请注意,这remove
是一个jqLite方法(如果jQuery在AngularjS之前加载,则为jQuery方法),并且在标准DOM元素对象上不可用。
当element.remove()
执行该元素及其所有子元素时,将从所有DOM中一起删除所有事件处理程序,例如element.on
。
它不会破坏与该元素关联的$ scope。
为了使其更加混乱,还有一个名为的jQuery事件$destroy
。有时,当使用删除元素的第三方jQuery库时,或者如果您手动删除它们,则可能需要在发生这种情况时执行清理:
element.on('$destroy', function () {
scope.$destroy();
});
指令被“销毁”时该怎么办
这取决于该指令如何被“销毁”。
通常的情况是由于ng-view
更改当前视图而导致指令被销毁。发生这种情况时,ng-view
指令将销毁关联的$ scope,切断对其父范围的所有引用并调用remove()
元素。
这意味着,如果该视图在被以下命令破坏时,其链接函数中包含带有此指令的指令ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
这两个事件监听器都将被自动删除。
但是,请务必注意,这些侦听器中的代码仍然会导致内存泄漏,例如,如果您已经实现了常见的JS内存泄漏模式circular references
。
即使在正常情况下,由于视图更改而导致指令被销毁的情况下,也可能需要手动清除某些内容。
例如,如果您在上注册了侦听器$rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
这是必需的,因为$rootScope
它在应用程序的生命周期中从未被破坏。
如果您使用的是另一个pub / sub实现,当$ scope被销毁时,或者您的指令将回调传递给服务,则该实现也不会自动执行必要的清理,情况也是如此。
另一种情况是取消$interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
如果您的指令将事件处理程序附加到例如当前视图之外的元素,则还需要手动清除它们:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
这些是Angular(例如ng-view
或)“销毁”指令时的操作示例ng-if
。
如果您具有管理DOM元素等生命周期的自定义指令,那么它当然会变得更加复杂。