Почему 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>
Ответы
Ответ 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();
});
});