Почему мой селектор jQuery не замечает, когда я удаляю класс?

У меня есть элемент, содержащийся в родительском элементе с классом active, например:

<div class="active">
    <div class="button"></div>
</div>

У меня есть jQuery, настроенный для обработки щелчка по моему button div, но только если этот div содержится в active родителе, например:

$('.active .button').click(function(){
    alert('Button clicked!');
});

Я использую jQuery для удаления класса active из родительского, и даже после удаления класса предупреждение все равно появляется, когда я нажимаю кнопку. Это кажется очень необычным, поскольку кнопка больше не соответствует критериям селектора. Это происходит в Chrome, Firefox и IE, поэтому кажется, что это намеренное поведение. Я что-то упускаю? или есть хотя бы простой способ обойти это?

Вот простой пример JSFiddle для тестирования: http://jsfiddle.net/KjuDy/. Щелкните поле в верхнем ряду. При этом появляется предупреждение и, как и ожидалось, удаляется класс active. Проблема возникает, когда вы щелкаете поле в верхней строке даже после того, как класс active исчез. Я ожидал, что предупреждение не появится, но оно все равно появляется.


person Michael Martin-Smucker    schedule 11.01.2011    source источник


Ответы (2)


Обработчики назначаются один раз на основе результатов, найденных в селекторе при его запуске (я предполагаю, что DOM готов).

Последующее изменение класса этих элементов не влияет на связанные обработчики.

Если вы хотите сделать его более динамичным, поместите обработчик .delegate() вместо предка элементов,

$('#someContainer').delegate('.active .button','click',function(){
    alert('Button clicked!');
});

Если единственным контейнером, который включает в себя все элементы, является <body>, используйте это:

$('body').delegate('.active .button','click',function(){
    alert('Button clicked!');
});

Ваш пример обновлен: http://jsfiddle.net/KjuDy/1/

person user113716    schedule 11.01.2011
comment
Спасибо! Это отлично сработало не только в упрощенном примере jsfiddle, но и в моем реальном проекте. Мне нужно немного почитать, чтобы я действительно понял, что здесь происходит, но, по крайней мере, мой проект на данный момент работает. - person Michael Martin-Smucker; 12.01.2011
comment
@ mlms13: Чтобы дать краткий обзор, функция .delegate() использует делегирование событий. Многие типы пузырей на странице. Другими словами, если вы щелкнете страницу, а затем, начиная с самого глубокого вложенного элемента, который был нажат, он проверит, есть ли обработчик щелчка, назначенный этому элементу. Если это так, он его вызывает. Затем он переходит к родительскому элементу и делает то же самое, и так далее, пока не достигнет корня документа. С делегированием событий вы размещаете обработчик событий в родительском контейнере. Затем событие щелчка, которое происходит внутри контейнера, всплывет к нему ... - person user113716; 12.01.2011
comment
... и уволить своего обработчика. Таким образом, метод jQuery .delegate() конкретно работает: первый аргумент, который вы передаете, - это селектор, который будет использоваться для проверки элемента внутри контейнера, по которому был выполнен щелчок. В вашем случае вы передаете .active .button. Таким образом, любой элемент внутри контейнера, который при нажатии соответствует этому селектору, jQuery запускает обработчик. Вот почему нажатие на .button, которое происходит от .active, вызовет обработчик, но когда вы удалите класс active, эта же кнопка больше не будет работать, потому что она больше не соответствует селектору. Надеюсь это поможет. - person user113716; 12.01.2011
comment
(примечание сбоку) .live() работает так же, за исключением того, что контейнер всегда является document, что означает, что он должен проверять каждый щелчок на странице по отношению к каждому селектору было дано. Многие этого не знают. Вот почему я всегда рекомендую .delegate(), поскольку это заставляет человека думать о том, какой конкретный контейнер использовать, вместо того, чтобы слепо использовать document. - person user113716; 12.01.2011

jQuery привязывается к элементам DOM, которые совпадают при первой привязке события щелчка.

Посмотрите на jQuery live.

person Zach    schedule 11.01.2011