使用绑定自取消事件

Self canceling events using bind

我在这里寻找的是一种从该方法中引用绑定方法的方法,目的是从事件侦听器中删除事件侦听器。

我想创建一个方法来处理几个不同事件的相同操作。

我有一个处理元素旋转的函数,名为 rotateActiveItem。它查看列表项列表并一次激活一个。

在我的构造函数中,我想设置一些(可能很多)触发 rotateLoadingCopy 的事件。

this.oneQuarter = genericDurationEvent.bind(this, animationDuration * .25);
this.half = genericDurationEvent.bind(this, animationDuration * .5);
this.threeQuarters = genericDurationEvent.bind(this, animationDuration * .75);

这些都被添加到动画的事件中:

this.animation_.addEventListener('enterFrame', this.oneQuarter);
this.animation_.addEventListener('enterFrame', this.half);
this.animation_.addEventListener('enterFrame', this.threeQuarters);

然后事件检查持续时间,执行轮换,然后应将其自身从 eventListeners 中移除。

genericDurationEvent(duration, event) {
  if (event.currentTime >= duration) {
    // Activate the next loading text element.
    this.rotateActiveItem();

    // Stop listening for this event.
    this.animation_.removeEventListener('enterFrame', /*What goes here?*/);
  }
}

起初我想也许我可以将绑定方法绑定到另一个方法上,但那是绑定函数的兔子洞。

然后我想 arguments.callee 会这样做,但我在严格模式下,它在严格模式下已被弃用。

我建议采用闭包模式,并动态生成处理程序,这样您就可以保留对函数的引用。

genericDurationEvent(context, duration) {
  var handler = function (event) {
    if (event.currentTime >= duration) {
      // Activate the next loading text element.
      this.rotateActiveItem();

      // Stop listening for this event.
      this.animation_.removeEventListener('enterFrame', handler);
    }
  }.bind(context);
  return handler;
}

this.oneQuarter = genericDurationEvent(this, animationDuration * .25);
this.half = genericDurationEvent(this, animationDuration * .5);
this.threeQuarters = genericDurationEvent(this, animationDuration * .75);

如果你想更进一步,你可以通过生成器使任何函数表现得像 "once" ala jQuery#one() 的方式隔离逻辑:

// definition
function once (what, eventName, originalHandler) {
  function onceHandler (...args) {
    what.removeEventListener(eventName, onceHandler);
    return originalHandler.apply(this, args);
  };
  what.addEventListener(eventName, onceHandler);
}

// usage
once(this.animation_, 'enterFrame', event => {
  if (event.currentTime >= animationDuration * .25) {
    // Activate the next loading text element.
    this.rotateActiveItem();
  }
});