简体   繁体   English

为什么jQuery选择事件监听器多次触发?

[英]Why is jQuery select event listener triggering multiple times?

Please run this sample in Google Chrome browser. 请在Google Chrome浏览器中运行此示例

Stack Snippet 堆栈代码段

 $(function() { $(":input").select(function() { $("div").text("Something was selected").show().fadeOut(1000); alert("Selected"); }); $("button").click(function() { $(":input").select(); }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <button>Click To Select</button> <input type="text" value="Some text"> <div></div> 

Here why jQuery select event listener is triggering multiple times? 这里为什么jQuery select事件监听器会多次触发? Does anyone know the reason behind this? 有谁知道这背后的原因? And is there any workaround solution for this without using timeout? 有没有使用超时的解决方案?

The $(":input") selector is selecting the button too, so it causes recursion. $(":input")选择器也在选择按钮,因此它会导致递归。 Either use just $("input") , or $(":input:not(button)") . 要么只使用$("input") ,要么使用$(":input:not(button)")

I noticed when the three events are fired, the first doesn't have originalEvent property, so we definitely can dismiss it, and the second two has very similar (however not identical) timestamp. 我注意到当三个事件被触发时,第一个没有originalEvent属性,所以我们绝对可以忽略它,而后两个具有非常相似(但不相同)的时间戳。 You can store the last timestamp in some variable and in event listener compare it with the event's timestamp. 您可以将最后一个时间戳存储在某个变量中,并在事件侦听器中将其与事件的时间戳进行比较。 If the rounded values of these two are the same, you can dismiss this event. 如果这两者的舍入值相同,则可以忽略此事件。

$(function() {
  var lastTimeStamp;
  $("input").select(function(event) {
    if (!event.originalEvent ||
        lastTimeStamp === Math.round(event.timeStamp)) return;
    lastTimeStamp = Math.round(event.timeStamp);
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $("input").select();
  });
});

See updated JS Fiddle . 查看更新的JS Fiddle

It appears the issue is a combination of: 看来这个问题是以下几个方面的组合:

  • the :input selector gets the input and the button , hence multiple events triggered. :input选择器获取inputbutton ,因此触发了多个事件。
  • even when using just input as the selector there is some odd event propagation being triggered on related elements which is raising the select event handler multiple times. 即使仅使用input作为选择器,也会在相关元素上触发一些奇怪的事件传播,这会多次引发select事件处理程序。

To avoid both of the above, use input as the selector and also use preventDefault() in the event handler. 要避免上述两种情况,请使用input作为选择器,并在事件处理程序中使用preventDefault() stopPropagation() may also be required, depending on your HTML stucture. 也可能需要stopPropagation() ,具体取决于您的HTML结构。

$(function() {
    $('input').select(function(e) {
        // e.stopPropagation(); // optional
        e.preventDefault();
        $('#message').text("Something was selected").show().fadeOut(1000);
        console.log('Selected');
    });

    $('button').click(function() {
        $('input').select();
    });
});

Working example 工作实例

UPDATE: We were all fooled. 更新:我们都被骗了。 The select() function needs a prevent default. select()函数需要一个prevent default。

Rory McCrossan figured it out. Rory McCrossan明白了这一点。 Well done mate. 做得好的队友。

Incidentally, I'm not sure what the benefit of select() actually is! 顺便说一下,我不确定select()实际上有什么好处! Something like focus() or on('focus',) might make more sense. 像focus()或on('focus')之类的东西可能更有意义。 Not Sure what the context is however. 但不确定上下文是什么。 The below still follows: 以下仍然如下:

Why waste time using generalised tag/type selectors which may change? 为什么浪费时间使用可能会改变的通用标签/类型选择器? Use an ID, and pick out only the one you want. 使用ID,只选择您想要的ID。

If you want to detect multiple, use a class. 如果要检测多个,请使用类。 If you want to use multiple, but figure out which one you clicked, use a class and an ID. 如果您想使用多个,但要确定您单击了哪一个,请使用类和ID。 Bind with the class, and identify using $this.attr('id') . 与类绑定,并使用$this.attr('id')

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text" id="pick-me">
<div></div>
$(function() {
  $("#pick-me").select(function(event) {
    event.preventDefault();
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $("#pick-me").select();
  });
});

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

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