简体   繁体   English

JavaScript,停止额外的事件监听器

[英]JavaScript, stop additional event listeners

Imagine I have this code:想象一下我有这段代码:

var myFunc1 = function(event) {
    alert(1);
}
var myFunc2 = function(event) {
    alert(2);
}

element.addEventListener('click', myFunc1);
element.addEventListener('click', myFunc2);

When the click event is fired myFunc1 is called, then myFunc2.当点击事件被触发时,myFunc1 被调用,然后是 myFunc2。 But how do I (if at all possible) stop myFunc2 from being called if some condition in myFunc1 is met?但是,如果满足 myFunc1 中的某些条件,我该如何(如果可能的话)停止调用 myFunc2 呢? event.stopPropagation() is not the solution, as this is not an event capturing/bubbling problem. event.stopPropagation()不是解决方案,因为这不是事件捕获/冒泡问题。

Thanks.谢谢。

The DOM Level 3 method event.stopImmediatePropagation is exactly what I need here. DOM Level 3 方法event.stopImmediatePropagation正是我在这里需要的。 Unfortunately, it's not currently implemented in any browser (that I know of)不幸的是,它目前没有在任何浏览器中实现(据我所知) . .

There's a further problem: the order that event listeners are executed is undefined.还有一个问题:事件侦听器的执行顺序未定义。 You'll need to handle event dispatch on your own to get around this, which leads us to some variant of llimllib's suggestion.您需要自己处理事件分派来解决这个问题,这使我们想到了 llimllib 建议的一些变体。

function dispatchSleightEvent(evt) {
    var listeners = evt.currentTarget.sleightListeners[evt.type];
    // can't use for-in because enumeration order is implementation dependent
    for (var i=0; i<listeners.length; ++i) {
       if (listeners[i]) {
         if (! listeners[i].call(evt.currentTarget, evt)) {
           return false;
         }
       }
    }
    return true;
}

function mixinSleightTarget(obj) {
  if (! obj.sleightListeners) {
    obj.sleightListeners = {}
    obj.addSleightListener = function(type, listener) {
        if (!this.sleightListeners[type]) {
            this.sleightListeners[type] = [];
            this.addEventListener(type, dispatchSleightEvent);
        }
        if (!this.sleightListeners[type+listener] {
          this.sleightListeners[type+listener] = this.sleightListeners[type].length;
          this.sleightListeners[type].push(listener);
        }
    }
    obj.removeSleightListener = function(type, listener) {
        if (this.sleightListeners[type+listener] {
          delete this.sleightListeners[type][this.sleightListeners[type+listener]];
          delete this.sleightListeners[type+listener];
        }          
    }
  }
}

This code is completely untested.此代码完全未经测试。 To stop event dispatch while on a single target, an event listener returns false .要在单个目标上停止事件调度,事件侦听器返回false If you want more data hiding, you can rewrite the above from a functional programming standpoint, though this might introduce memory leaks.如果你想要更多的数据隐藏,你可以从函数式编程的角度重写上面的代码,尽管这可能会引入内存泄漏。

Still looking for a better solution, but this may be the only way to do it:仍在寻找更好的解决方案,但这可能是唯一的方法:

var myFunc1 = function(event) {
    alert(1);
    if (something) {
        event.cancel = true;
    }
}
var myFunc2 = function(event) {
    if (event.cancel) {
        return;
    }
    alert(2);
}

document.body.addEventListener('click', myFunc1, false);
document.body.addEventListener('click', myFunc2, false);

Thoughts/comments welcome.欢迎思考/评论。

I'll start with the simplest answer that satisfies the constraints you've given so far.我将从满足您目前给出的限制的最简单答案开始。 If it doesn't meet some condition you haven't yet specified, let me know and I'll update it.如果它不满足您尚未指定的某些条件,请告诉我,我会更新它。

Only allow one click handler, and call functions based on conditions there.只允许一个点击处理程序,并根据那里的条件调用函数。 Your test code becomes:您的测试代码变为:

var myFunc1 = function(event) {
    alert(1);
}
var myFunc2 = function(event) {
    alert(2);
}
var clickHandler = function(event) {
    if (f1active) myFunc1(event);
    if (f2active) myFunc2(event);
}

element.addEventListener('click', clickHandler);
var f1active = true;
var f2active = true;

and you can of course put any conditions you want to in clickHandler.您当然可以在 clickHandler 中放置任何您想要的条件。

I second the outis solution, sounds like you need to decorate or adapt the existing DOM event dispatching model with your own event dispatcher.我支持 outis 解决方案,听起来您需要使用自己的事件调度程序来装饰或调整现有的 DOM 事件调度模型。

Did some searching and found this link, which may or may not suit your needs, based on an actionscript dispatcher implementation, dated 2007.根据 2007 年的 actionscript 调度程序实现,做了一些搜索并找到了这个链接,它可能适合也可能不适合您的需要。

http://positionabsolute.net/blog/2007/06/event-dispatcher.php http://positionabsolute.net/blog/2007/06/event-dispatcher.php

Web archive link: https://web.archive.org/web/20170330152239/http://positionabsolute.net/blog/2007/06/event-dispatcher.php网络存档链接: https ://web.archive.org/web/20170330152239/http://positionabsolute.net/blog/2007/06/event-dispatcher.php

Of course I'm not really a javascripter, so give me a heads up if this is not relevant.当然,我不是真正的 javascripter,所以如果这不相关,请提醒我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM