Подтвердить что ты не робот

Почему jQuery несколько раз запускает прослушиватель событий?

Пожалуйста, запустите этот образец в браузере Google Chrome.

Фрагмент стека

$(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>
4b9b3361

Ответ 1

Селектор $(":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();
  });
});

Смотрите обновленный JS Fiddle.

Ответ 2

Кажется, проблема состоит в следующем:

  • Селектор :input получает input и button, поэтому срабатывает несколько событий.
  • даже при использовании только 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();
    });
});

Рабочий пример

Ответ 3

ОБНОВЛЕНИЕ: нас всех обманули. Функция select() нуждается в предотвращении по умолчанию.

Рори Маккроссан понял это. Хорошо сделанный помощник.

Кстати, я не уверен, какая польза от select() на самом деле! Что-то вроде focus() или on ( "focus",) может иметь больше смысла. Не уверен, что такое контекст. Ниже следует следующее:

Зачем тратить время на использование обобщенных селекторов тегов/типов, которые могут измениться? Используйте идентификатор и выберите только тот, который вы хотите.

Если вы хотите обнаружить несколько, используйте класс. Если вы хотите использовать несколько, но выяснить, какой из них вы нажали, используйте класс и идентификатор. Свяжите с классом и определите с помощью $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();
  });
});