【问题标题】:How can I tell if an event is being fired by the same event that created it?如何判断一个事件是否被创建它的同一事件触发?
【发布时间】:2014-03-05 14:17:10
【问题描述】:

假设我有以下事件:

$(button).on('mouseup', function (event1) {
    $(something).show();

    $(document).on('mouseup', function (event2) {
        $(something).hide();
    });

});

因此,单击按钮时它会显示“某些东西”,单击文档时会隐藏它。如何确保第二个 evnet 不会在创建它的同一事件中触发?现在这些东西会立即显示和隐藏(至少在 Firefox 上)。

我需要在没有任何类型的全局变量的情况下执行此操作,最好是。

【问题讨论】:

  • 从事件处理程序中设置事件处理程序几乎总是错误的(就像这里一样)。与其关注机制,不如描述你的目标。
  • 这会在文档中添加新的 mouseup 事件,每次释放按钮时?除此之外,您是否尝试过使用console.log(event1)console.log(event2),看看会得到什么?事件在 jQuery 中有 target 属性,你可以使用它。不过,您需要修复您的代码。
  • @D.Kasipovic 这很奇怪。我尝试比较时间戳,如果我只是记录事件,它会显示它们,但如果我在 if 语句中使用它们,它会将它们显示为未定义。我将更改问题以说明如何;
  • @D.Kasipovic 没关系,我是个白痴。我使用了 event.timestamp 而不是 event.timeStamp。现在可以了。我不知道是要更改问题以包含答案还是自己回答....
  • 我同意@Jon 的观点,你几乎肯定做错了。但至少,您应该将.on 替换为.one,这样您的嵌套事件只会触发一次然后被删除。否则,您将堆积.mouseup 事件处理程序,直到您的网页停止运行。

标签: javascript jquery


【解决方案1】:

这个怎么样:

$(button).on('mouseup', function (event1) {
    $(something).show();
    event1.stopPropagation();
    $(document).one('mouseup', function (event2) {
        $(something).hide();
    });

});

stopPropagation() 将阻止事件越过按钮(到文档)。

one() 只会运行一次事件然后消失...可以再次单击按钮重新创建。

JSFiddle

【讨论】:

  • 如果我有多个按钮,stopPropagation 将允许显示多个内容。这是一个解决方案,但马特的更好
  • @Bogdan,你没有提到这一点,但是我不确定马特的会有什么不同......除了他的,点击按钮也会隐藏。如果你想要最好的解决方案,你应该展示你的 dom(或它的样本)。另外,show() 只是显示......它不会创建多个,所以我不确定你的意思:jsfiddle.net/v7Yrr/1
  • 是的,对不起,我想得太早了。这只是一个例子,我的代码更复杂,show() 和 hide() 函数被传递给我的组件的回调替换
【解决方案2】:

这是另一个不依赖时间戳的解决方案:

$("button").on('mouseup', function (event1) {
    $("#something").show();

    setTimeout(function () {
        $(document).one('mouseup', function (event2) {
             $("#something").hide();
        });
    }, 0);

}); 

demo

使用延迟为 0 的 setTimeout 将使其在完成此事件后立即执行代码。另请注意,我使用的是one 而不是on,因为您只需要一次这个事件处理程序,如果没有它,您最终将附加无限数量的事件处理程序,当mouseup 时,每个事件处理程序都需要处理触发页面上的任何位置。

一个不那么愚蠢的解决方案可能如下所示:

$("button").on('mouseup', function (event1) {
     $("#something").show();
});

$(document).on('mouseup', function (event2) {
    if(event2.target != $("button")[0]) {
        $("#something").hide();
    }
});

demo

【讨论】:

  • 即使我使用了我的答案,我也会接受这个答案。这个答案更中肯。
  • 不太傻的解决方案在功能上与第一个不同。它也没有回答具体问题。谢谢你的第一个,没有考虑过使用超时。
  • @Bogdan:功能上是一样的。它实现了相同的目标,即在您单击按钮时出现某些内容,并在您单击其他任何位置时消失。它的功能相同。唯一的技术区别在于,第二种解决方案总是将mouseup 处理程序附加到文档中,其中第一个解决方案仅在有人单击按钮时才附加处理程序。
【解决方案3】:

你为什么不像这样隔离事件:

$(button).on('mouseup', function (event1) {
    $(something).show();
});

$(document).on('mouseup', function (event2) {
        $(something).hide();
});

【讨论】:

  • 即便如此,在整个文档上放置一个'mouseup'事件也是不行的。它可以覆盖您的按钮事件
  • 这通常不太好,但我正在构建一个弹出/弹出框组件,我需要一种方法来在用户单击文档上的任意位置时关闭弹出框。
  • stackoverflow.com/questions/14205921/… 看看这个解决方案看起来更优雅
  • 是的,它更优雅,但对我也没有用。我正在构建它是为了对弹出/弹出框进行非常广泛的定义。我将它留给组件的用户来声明显示/隐藏功能和显示/隐藏条件。这就是为什么我需要这种“丑陋”的事件结构。
【解决方案4】:

我最终使用 event.timeStamp 属性来检查这两个事件是否不同。还为文档事件添加了 unbind 和命名空间,以防止事件堆叠。

$(button).on('mouseup', function (event1) {
    $(something).show();

    $(document).on('mouseup.'+someIdentifier, function (event2) {
        if(event1.timeStamp != event2.timeStamp) {
            $(something).hide();
            $(document).unbind('mouseup.'+someIdentifier);
        }
    });

});

【讨论】:

  • 对于隐藏和显示元素来说太复杂了。
  • 这不仅仅是为了隐藏或显示一个元素。问题是关于区分这两个事件,我认为对于点击事件,时间戳是一个很好的区分因素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 2012-04-02
  • 2015-07-08
  • 1970-01-01
相关资源
最近更新 更多