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

Joh*_*n R 21 html javascript jquery dom google-chrome

请在Google Chrome浏览器中运行此示例.

堆栈代码段

$(function() {
  $(":input").select(function() {
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $(":input").select();
  });
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这里为什么jQuery select事件监听器会多次触发?有谁知道这背后的原因?有没有使用超时的解决方案?

Mic*_*ski 14

$(":input")选择器选择按钮太多,所以它会导致递归.要么只使用$("input"),要么$(":input:not(button)").

我注意到当三个事件被触发时,第一个没有originalEvent属性,所以我们绝对可以忽略它,而后两个有非常相似(但不完全相同)的时间戳.您可以将最后一个时间戳存储在某个变量中,并在事件侦听器中将其与事件的时间戳进行比较.如果这两者的舍入值相同,则可以忽略此事件.

$(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();
  });
});
Run Code Online (Sandbox Code Playgroud)

查看更新的JS Fiddle.


Ror*_*san 10

看来这个问题是以下几个方面的组合:

  • :input选择获取inputbutton,因此多个事件触发.
  • 即使在仅使用input选择器时,也会在相关元素上触发一些奇怪的事件传播,这会select多次引发事件处理程序.

要避免上述两种情况,请将其input用作选择器并preventDefault()在事件处理程序中使用.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();
    });
});
Run Code Online (Sandbox Code Playgroud)

工作实例

  • @RoryMcCrossan`e.preventDefault()`将阻止选择文本. (3认同)