Як запустити подію при зміні класу за допомогою jQuery?


Відповіді:


169

При зміні класу не відбувається жодної події. Альтернатива - вручну викликати подію, коли ви програмно змінюєте клас:

$someElement.on('event', function() {
    $('#myDiv').addClass('submission-ok').trigger('classChange');
});

// in another js file, far, far away
$('#myDiv').on('classChange', function() {
     // do stuff
});

ОНОВЛЕННЯ

Здається, це питання збирає деяких відвідувачів, тому ось оновлення з підходом, яке можна використовувати без необхідності модифікувати існуючий код, використовуючи новий MutationObserver:

var $div = $("#foo");
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.attributeName === "class") {
      var attributeValue = $(mutation.target).prop(mutation.attributeName);
      console.log("Class attribute changed to:", attributeValue);
    }
  });
});
observer.observe($div[0], {
  attributes: true
});

$div.addClass('red');
.red { color: #C00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" class="bar">#foo.bar</div>

Майте на увазі, що MutationObserverвін доступний лише для нових браузерів, зокрема Chrome 26, FF 14, IE 11, Opera 15 та Safari 6. Детальніше див. MDN . Якщо вам потрібно підтримати застарілі браузери, то вам доведеться скористатися методом, який я описав у своєму першому прикладі.


На завершення цієї відповіді я знайшов таке: stackoverflow.com/a/1950052/1579667
Бень

1
@Benj Це те саме, що і моя оригінальна відповідь (тобто використання trigger()), хоча зауважте, що вона дуже застаріла через використання bind(). Я не впевнений, як це щось "завершує",
Рорі Маккроссан

У моєму випадку мені потрібно було запустити подію, коли на вузлі dom існує певний клас, який MutationObserverпрацює для мене
Mario

1
Це покращена форма цього розчину з фільтром stackoverflow.com/a/42121795/12074818
MVDeveloper1

20

Ви можете замінити оригінальну функцію jQuery addClass та removeClass на власну, яка викликала б вихідні функції, а потім ініціювала власну подію. (Використання анонімної функції, що викликається самостійно, щоб містити вихідне посилання на функцію)

(function( func ) {
    $.fn.addClass = function() { // replace the existing function on $.fn
        func.apply( this, arguments ); // invoke the original function
        this.trigger('classChanged'); // trigger the custom event
        return this; // retain jQuery chainability
    }
})($.fn.addClass); // pass the original function as an argument

(function( func ) {
    $.fn.removeClass = function() {
        func.apply( this, arguments );
        this.trigger('classChanged');
        return this;
    }
})($.fn.removeClass);

Тоді решта вашого коду буде настільки простою, як ви очікували.

$(selector).on('classChanged', function(){ /*...*/ });

Оновлення:

Цей підхід робить припущення, що класи будуть змінені лише за допомогою методів jQuery addClass та removeClass. Якщо класи модифікуються іншими способами (наприклад, безпосередня маніпуляція атрибутом класу через елемент DOM), MutationObserverбуде потрібно щось на зразок s, як пояснюється у прийнятій відповіді.

Також як пара вдосконалення цих методів:

  • Викликати подію для кожного класу, який додається ( classAdded) або видаляється ( classRemoved) із зазначеним класом, переданим як аргумент функції зворотного виклику, і запускається, лише якщо конкретний клас був фактично доданий (раніше не був присутній) або видалений (був раніше)
  • Спрацьовувати лише в тому classChangedвипадку, якщо якісь класи насправді змінено

    (function( func ) {
        $.fn.addClass = function(n) { // replace the existing function on $.fn
            this.each(function(i) { // for each element in the collection
                var $this = $(this); // 'this' is DOM element in this context
                var prevClasses = this.getAttribute('class'); // note its original classes
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString(); // retain function-type argument support
                $.each(classNames.split(/\s+/), function(index, className) { // allow for multiple classes being added
                    if( !$this.hasClass(className) ) { // only when the class is not already present
                        func.call( $this, className ); // invoke the original function to add the class
                        $this.trigger('classAdded', className); // trigger a classAdded event
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged'); // trigger the classChanged event
            });
            return this; // retain jQuery chainability
        }
    })($.fn.addClass); // pass the original function as an argument
    
    (function( func ) {
        $.fn.removeClass = function(n) {
            this.each(function(i) {
                var $this = $(this);
                var prevClasses = this.getAttribute('class');
                var classNames = $.isFunction(n) ? n(i, prevClasses) : n.toString();
                $.each(classNames.split(/\s+/), function(index, className) {
                    if( $this.hasClass(className) ) {
                        func.call( $this, className );
                        $this.trigger('classRemoved', className);
                    }
                });
                prevClasses != this.getAttribute('class') && $this.trigger('classChanged');
            });
            return this;
        }
    })($.fn.removeClass);
    

За допомогою цих функцій заміни ви можете обробляти будь-який клас, змінений через classChanged, або додавати або видаляти конкретні класи, перевіряючи аргумент функції зворотного виклику:

$(document).on('classAdded', '#myElement', function(event, className) {
    if(className == "something") { /* do something */ }
});

1
Це працює відмінно, але в «решти коду» обробник подій повинен бути делегований цільової селектор , щоб прив'язка до нових елементів: $(parent_selector).on('classChanged', target_selector, function(){ /*...*/ });. Мені знадобився час, щоб зрозуміти, чому мої динамічно створені елементи не запускали обробник. Див. Learn.jquery.com/events/event-delegation
Timm

6

Використовуйте triggerдля запуску власної події. Коли ви коли-небудь змінюєте клас, додайте тригер з іменем

JS Fiddle DEMO

$("#main").on('click', function () {
    $("#chld").addClass("bgcolorRed").trigger("cssFontSet");
});

$('#chld').on('cssFontSet', function () {

    alert("Red bg set ");
});

Вивчайте jQuery: Простий та легкий блог з підручників з jQuery


2

Ви можете використовувати щось на зразок цього:

$(this).addClass('someClass');

$(Selector).trigger('ClassChanged')

$(otherSelector).bind('ClassChanged', data, function(){//stuff });

але в іншому випадку ні, немає жодної заздалегідь визначеної функції, яка запускає подію при зміні класу.

Детальніше про тригери читайте тут


1
Обробником події повинен бути той самий елемент, який ініціює подію. $ (this) .addClass ('someClass'); $ (Selector) .trigger ('ClassChanged') // Це повинен бути той самий Selector $ (Selector) .bind ('ClassChanged', data, function () {// stuff});
Меко Перес Естевес

3
Здається , ви скопіювали тут, якщо так , то добре , якщо ви надасте посилання занадто stackoverflow.com/questions/1950038 / ...
Сатіндер Singh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.