如何使用jQuery在类更改上触发事件?


Answers:


169

类更改时不会引发任何事件。另一种方法是在以编程方式更改类时手动引发事件:

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

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

更新

这个问题似乎正在吸引一些访问者,因此这里是一种更新方法,可以使用该方法而不必使用new修改现有代码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和Safari6。有关更多详细信息,请参见MDN。如果需要支持旧版浏览器,则需要使用我在第一个示例中概述的方法。


完成此答案后,我发现了这个问题:stackoverflow.com/a/1950052/1579667
Benj

1
@Benj与我的原始答案相同(即使用trigger()),但请注意,由于使用,它已经过时了bind()。不过,我不确定它如何“完成”任何事情
罗里·麦克罗斯

在我来说,我需要的时候DOM节点都有一个特定的类触发事件MutationObserver对我的作品
马里奥

这是此解决方案的改进形式,带有过滤器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元素直接对class属性进行操作),则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,


2

您可以使用以下方式:

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

$(Selector).trigger('ClassChanged')

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

但是否则,没有预定义的函数可以在类更改时触发事件。

在此处阅读有关触发器的更多信息


1
事件的处理程序必须与触发事件的项目相同。$(this).addClass('someClass'); $(Selector).trigger('ClassChanged')//必须是相同的选择器$(Selector).bind('ClassChanged',data,function(){// stuff});
Meko Perez Estevez

3
看来你已经从这里复制的,如果是的话那么,如果你提供的链接太好stackoverflow.com/questions/1950038/...
Satinder辛格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.