Angular Renderer2 移除侦听器将 EventListeners 留在内存中 - 内存泄漏?

Angular Renderer2 remove listener leaves EventListeners in memory - memory leak?

我在指令中有 3 个事件侦听器,我在按钮切换和删除时添加和删除

private addListeners() {
    this.mouseLeaveFunc = this.renderer.listen(this.el.nativeElement, 'mouseleave', () => {

    });
    this.mouseEnterFunc = this.renderer.listen(this.el.nativeElement, 'mouseenter', () => {

    });
    this.onClickFunc = this.renderer.listen(this.el.nativeElement, 'click', (event) => {

    });
}

 private removeListeners() {
    if (this.mouseLeaveFunc) {
        this.mouseLeaveFunc();
        this.mouseEnterFunc();
        this.onClickFunc();
    }
}

移除监听器后 Angular 不再监听它们但是比较第一次点击和第二次点击后的内存转储我看到第二次有 9 个监听器(我在页面上有 3 个指令所以 3 el x 3 个听众)。

任何想法是内存泄漏还是如何删除它们?

嗯...您似乎 运行 Angular 处于开发模式。您的 EventListeners 可能附加到 Angular 的 DebugElement。如果您使用 Renderer2 创建和删除节点,您可能还会注意到所有 Detached HTMLElement 都保留在内存中。

不要太担心,因为这一切在生产模式下都会消失。

Btw whats an advantage of adding listeners via renderer?

省去了手动移除事件监听器的麻烦。如果您将 addEventListenerremoveEventListener 与纯 JavaScript 一起使用,您将必须命名您的侦听器函数。如果您需要执行一些数据操作,传递 class 参数也会很痛苦:How to pass arguments to addEventListener listener function?

Renderer 的 listen 方法支持监听和取消监听匿名函数,支持 class 引用您的组件的函数 class(addEventListener 不支持 - 使用 addEventListener, this 将指向目标元素,而不是您的组件 class) 并轻松支持使用附加参数调用侦听器函数。它用途广泛且安全,让您记住不要听。

此外,Angular 的不听机制比调用 removeEventListener 更可靠。 removeEventListener 要求开发人员提供确切的参数,很容易失败,并且没有 return 值或通知告诉您是否已成功删除某些内容。使用 Renderer2,您几乎可以保证删除正确的 EventListener。