【问题标题】:Javascript removeEventListener OnDestroy not working in Angular 6Javascript removeEventListener OnDestroy 在 Angular 6 中不起作用
【发布时间】:2018-11-16 18:49:21
【问题描述】:

我正在尝试 removeEventListener 在我的角度组件中:Javascript removeEventListener not working

    ...
    ngOnInit() {
        document.addEventListener('visibilitychange', () =>this.handleVisibleState(), true);
    }

    ngOnDestroy() {
        document.removeEventListener('visibilitychange', () => this.handleVisibleState(), true);
    }

    handleVisibleState() {
        let vis = document.visibilityState === 'visible';
        this.configsService.update_collab_visible(vis);
    }
    ...

即使在ngOnDestroy () 之后,上面的addEventListener 也可以工作

如何在角度组件中从文档中解除可见性状态的绑定?

尝试 2

    private visibilityChangeCallback: () => void;

    ngOnInit() {
        this.visibilityChangeCallback = () => this.handleVisibleState();
        document.addEventListener('visibilitychange', this.handleVisibleState, true);
    }

    ngOnDestroy() {
        document.removeEventListener('visibilitychange', this.handleVisibleState, true);
    }

    handleVisibleState() {
        let vis = document.visibilityState === 'visible';
        console.log(typeof this.configsService); // undefined
        this.configsService.update_collab_visible(vis);
    }

结果:

错误类型错误:无法读取未定义的属性“update_collab_visible”

【问题讨论】:

  • 如果你在 Angular 中使用这个,你应该总是更喜欢 Renderer2 服务而不是直接修改 dom 节点。

标签: angular typescript angular-routing


【解决方案1】:

存储回调:

private visibilityChangeCallback: () => void;

ngOnInit() {
    this.visibilityChangeCallback = () => this.handleVisibleState();
    document.addEventListener('visibilitychange', this.visibilityChangeCallback, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.visibilityChangeCallback, true);
}

【讨论】:

  • 我猜self.handleVisibleState()应该是this.handleVisibleState()
  • 在您的编辑中,您仍在使用document.addEventListener('visibilitychange', this.handleVisibleState, true);
  • @Omar 我的回答基本上与@PierreDuc 的第一个建议一样,但我的回答创建了一个单独的函数,因此您不必将类方法handleVisibleState 更改为箭头函数。如果您不在乎,@PierreDuc 的更改会更简单。
【解决方案2】:

您必须使用箭头函数使函数成为类上的属性字段,而不是使用匿名函数,因为函数引用不会相同。

您收到Cannot read property 'update_collab_visible' of undefined 错误的原因是您使用的是类函数而不是类字段。这会将this 上下文移动到函数中,这不是您想要的:

ngOnInit() {
    document.addEventListener('visibilitychange', this.handleVisibleState, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.handleVisibleState, true);
}

handleVisibleState = () => {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
};

还有其他选择。我看到你想为事件使用捕获标志。你也可以考虑使用 rxjs lib:

destroy = new Subject<void>();

ngOnInit() {
  fromEvent(document, 'visibilitychange', true).pipe(
    takeUntil(this.destroy)
  ).subscribe((event) => this.handleVisibleState(event));
}

ngOnDestroy() {
  this.destroy.next();
  this.destroy.complete();
}

广告

还有一个 Angular 库,它为模板和组件事件绑定添加了功能,称为 ng-event-options。如果您已经安装/导入了它,您可以简单地使用:

@HostListener('document:visibilitystate.c')
handleVisibleState() {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
}

你就完成了

【讨论】:

  • 最后一个会自动销毁吗?
  • @Omar 是的,因为它使用库,并且当组件被销毁时,每个带有 HostListener 的事件都会被删除。这与在模板中使用事件绑定相同。您也不需要手动删除它
  • 不明白第三个选项的监听器是怎么注册的?
  • @Omar 阅读了有关@HostListener 的信息。它是一个 Angular 装饰器,用于绑定组件上的事件。但如果你使用document:window:body:,它会绑定到那个元素。之后是事件名称。 ng-event-options 增加了额外事件选项的可能性,例如捕获(以及更多)。这是由单个字符设置的。在这种情况下,c 代表 capture,这就是您的 addEventListener 中的 true 所做的
  • 我想在“停止”按钮单击时停止工作单击事件。并在“开始”按钮点击时重新启动点击事件。
【解决方案3】:

使用未标识任何当前在 EventTarget 上注册的 EventListener 的参数调用 removeEventListener() 无效。您正在将其他功能传递给它。

使用instance arrow function 应该对您的情况有所帮助:

ngOnInit() {
    document.addEventListener('visibilitychange', this.handleVisibleState, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.handleVisibleState, true);
}

handleVisibleState = () => {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
}

【讨论】:

    【解决方案4】:

    this.&lt;anything&gt; 不起作用的原因是this 的含义不同,因为它在回调中并且您没有绑定它。

    如果你 bind this 它应该可以工作。

    document.addEventListener('visibilitychange', this.handleVisibleState.bind(this), true);

    【讨论】:

    • OP 仍然需要存储 this.handleVisibleState.bind(this) 的结果以将其传递给 removeEventListener
    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 2014-09-02
    • 2022-12-31
    • 2016-09-18
    • 2018-11-25
    相关资源
    最近更新 更多