gpt4 book ai didi

AngularJS - $destroy 是否删除事件监听器?

转载 作者:行者123 更新时间:2023-12-02 19:14:34 27 4
gpt4 key购买 nike

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.

问题:

我的指令中有一个 element.on "click", (event) -> :

  1. 当指令被销毁时,是否存在对 element.on 的内存引用以防止其被垃圾回收?
  2. Angular 文档指出,我应该使用处理程序来删除 $destroy 发出的事件上的事件监听器。我的印象是 destroy() 删除了事件监听器,事实不是这样吗?

最佳答案

事件监听器

首先,了解有两种“事件监听器”很重要:

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

    $scope.$on('anEvent', function (event, data) {
    ...
    });
  2. 通过例如 onbind 附加到元素的事件处理程序:

    element.on('click', function (event) {
    ...
    });
<小时/>

$scope.$destroy()

当执行$scope.$destroy()时,它将删除通过该$scope上的$on注册的所有监听器。

不会删除 DOM 元素或任何附加的第二类事件处理程序。

这意味着从指令链接函数中的示例手动调用 $scope.$destroy() 不会删除通过例如 element.on 附加的处理程序,也不会DOM 元素本身。

<小时/>

element.remove()

请注意,remove 是一个 jqLit​​e 方法(如果 jQuery 在 AngularjS 之前加载,则为 jQuery 方法),并且在标准 DOM 元素对象上不可用。

当执行 element.remove() 时,该元素及其所有子元素将从 DOM 中一起删除,所有事件处理程序也会通过例如 element.on 附加。

不会破坏与该元素关联的$scope。

为了让它更加困惑,还有一个名为 $destroy 的 jQuery 事件。有时,当使用删除元素的第三方 jQuery 库时,或者如果您手动删除它们,则可能需要在发生这种情况时执行清理:

element.on('$destroy', function () {
scope.$destroy();
});
<小时/>

指令被“破坏”时该怎么办

这取决于指令如何被“销毁”。

正常情况是指令被销毁,因为 ng-view 更改了当前 View 。发生这种情况时,ng-view 指令将销毁关联的 $scope,切断对其父范围的所有引用,并在元素上调用 remove()

这意味着,如果该 View 在被 ng-view 销毁时,其链接函数中包含带有 this 的指令:

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

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

两个事件监听器都将自动删除。

但是,需要注意的是,这些监听器内的代码仍然可能导致内存泄漏,例如,如果您实现了常见的 JS 内存泄漏模式循环引用

即使在指令因 View 更改而被破坏的正常情况下,您也可能需要手动清理一些内容。

例如,如果您已在 $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);
});

如果您的指令将事件处理程序附加到当前 View 之外的元素,您还需要手动清理它们:

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

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

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

这些是当指令被 Angular(例如 ng-viewng-if)“破坏”时该怎么做的一些示例。

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

关于AngularJS - $destroy 是否删除事件监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26983696/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com