【问题标题】:Remove or destroy event listener移除或销毁事件监听器
【发布时间】:2017-04-23 06:03:29
【问题描述】:

正在开发 angular2 应用程序。我有 RxJS 计时器 实例,它会在登录时向用户推送通知。但它不应该推送通知如果选项卡未处于活动状态,则调度程序应该暂停/停止。也完成了。

但主要是我已将 window (focus, blur ) 事件侦听器添加到 ngOnInit()。当我们更改页面/组件时,我试图在 ngOnDestroy() 上销毁它,但它也不会停止。当我们回到同一页面时,该侦听器的第二个实例也开始了,现在我的内存/范围中将有 2 个调度程序实例。

所以任何人都知道如何在 ngOnDestroy 或任何其他地方删除/销毁 window.listener !

代码:

timerFlag: boolean = true;
private timer;
private sub: Subscription;

ngOnInit() {
    this.sub = null;
    this.timer = null;
    console.log("home-init");
    window.addEventListener('blur', this.disableTimer.bind(this), false);
    window.addEventListener('focus', this.initializeTimer.bind(this), false);
}
disableTimer() {
    if (this.sub !== undefined && this.sub != null) {
        this.sub.unsubscribe();
        this.timer = null;
    }
}
initializeTimer() {
    if (this.timerFlag) {
        if (this.timer == null) {
            this.timer = Observable.timer(2000, 5000);
            this.sub = this.timer.subscribe(t => this.runMe());
        }
    }
}
runMe() {
    console.log("notification called : " + new Date());
}
ngOnDestroy() {
    console.log("Destroy timer");
    this.sub.unsubscribe();
    this.timer = null;
    this.sub = undefined;
    this.timerFlag = false;
    window.removeEventListener('blur', this.disableTimer.bind(this), false);
    window.removeEventListener('focus', this.initializeTimer.bind(this), false);
}

谁能指导我如何销毁事件侦听器实例,以便下次访问同一页面时不会启动第二个实例。

我已经尝试在 ngOnInit 中删除监听器,以及在 window listener 开始之前。

【问题讨论】:

  • 被移除的监听器必须与添加的监听器相同(在=== 意义上)。 this.disabletimer.bind(this) 在您调用两次时相同。顺便说一句,这与 Angular 无关。这是一个纯粹的 JS 问题。
  • 那么,无论如何我可以删除监听器!
  • 是的,正如重复的问题所暗示的那样,将侦听器存储在一个变量中,然后使用该变量将其删除。
  • 作为下面的答案,对吧?

标签: javascript angular addeventlistener event-listener


【解决方案1】:

1) 我想这应该可行:

ngOnInit() {
  window.addEventListener('blur', this.disableTimer, false);
  window.addEventListener('focus', this.initializeTimer, false);
}

disableTimer = () => { // arrow function
  ...
}
initializeTimer = () => { // arrow function
  ... 
}

ngOnDestroy() {
  window.removeEventListener('blur', this.disableTimer, false);
  window.removeEventListener('focus', this.initializeTimer, false);
}

Plunker Example

2) 另一种方法是将监听器存储在变量中,因为 .bind 每次都会返回新函数

disableTimerFn: EventListenerOrEventListenerObject;

ngOnInit() {
  this.disableTimerFn = this.disableTimer.bind(this);
  window.addEventListener('blur', this.disableTimerFn, false); 
}

ngOnDestroy() {
  window.removeEventListener('blur', this.disableTimerFn, false);
}

Plunker Example

3)但也许最好的方法是使用angular2方式:

@HostListener('window:blur', ['$event'])
disableTimer (event) { ... }

组件销毁时会自动移除

Plunker Example

4) 还有一种 angular2 方式是使用Renderer

globalListenFunc: Function;
constructor(private renderer: Renderer) { }
ngOnInit() {
  this.globalListenFunc = this.renderer.listenGlobal('window', 'click', this.onClick.bind(this))
}

onClick() {
  alert('click');
}

ngOnDestroy() {
  this.globalListenFunc(); // destroy listener
}

Plunker Example

另见

【讨论】:

  • 如何将其存储在变量中?
  • 当我使用你的代码时,我的组件级私有成员显示我未定义,我认为这是由于我必须绑定它。有什么解决办法吗?
  • 第二种方式当我删除监听器时,它告诉我不能使用函数类型的参数......请有什么建议吗?
  • 尝试将Function改为EventListenerOrEventListenerObject
  • 对于第一个选项,我有所有组件级别的成员在函数内部都是未定义的。
猜你喜欢
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
相关资源
最近更新 更多