245

如果使用 jQuery 添加或更改 CSS 类,我如何触发事件?更改 CSS 类会触发 jQuerychange()事件吗?

4

13 回答 13

229

每当您更改脚本中的类时,您都可以使用 atrigger来引发您自己的事件。

$(this).addClass('someClass');
$(mySelector).trigger('cssClassChanged')
....
$(otherSelector).bind('cssClassChanged', data, function(){ do stuff });

但除此之外,不,当类发生变化时,没有固定的方法来触发事件。change()仅在焦点离开输入已更改的输入后触发。

$(function() {
  var button = $('.clickme')
      , box = $('.box')
  ;
  
  button.on('click', function() { 
    box.removeClass('box');
    $(document).trigger('buttonClick');
  });
            
  $(document).on('buttonClick', function() {
    box.text('Clicked!');
  });
});
.box { background-color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="box">Hi</div>
<button class="clickme">Click me</button>

更多关于 jQuery 触发器的信息

于 2009-12-23T00:23:15.597 回答
143

恕我直言,更好的解决方案是将@RamboNo5 和@Jason 的两个答案结合起来

我的意思是覆盖 addClass 函数并添加一个名为的自定义事件cssClassChanged

// Create a closure
(function(){
    // Your base, I'm in it!
    var originalAddClassMethod = jQuery.fn.addClass;

    jQuery.fn.addClass = function(){
        // Execute the original method.
        var result = originalAddClassMethod.apply( this, arguments );

        // trigger a custom event
        jQuery(this).trigger('cssClassChanged');

        // return the original result
        return result;
    }
})();

// document ready function
$(function(){
    $("#YourExampleElementID").bind('cssClassChanged', function(){ 
        //do stuff here
    });
});
于 2012-12-29T18:52:20.197 回答
62

如果你想检测类变化,最好的方法是使用 Mutation Observers,它可以让你完全控制任何属性变化。但是,您需要自己定义侦听器,并将其附加到您正在侦听的元素中。好消息是,一旦附加了侦听器,您就不需要手动触发任何东西。

$(function() {
(function($) {
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

    $.fn.attrchange = function(callback) {
        if (MutationObserver) {
            var options = {
                subtree: false,
                attributes: true
            };

            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(e) {
                    callback.call(e.target, e.attributeName);
                });
            });

            return this.each(function() {
                observer.observe(this, options);
            });

        }
    }
})(jQuery);

//Now you need to append event listener
$('body *').attrchange(function(attrName) {

    if(attrName=='class'){
            alert('class changed');
    }else if(attrName=='id'){
            alert('id changed');
    }else{
        //OTHER ATTR CHANGED
    }

});
});

在此示例中,事件侦听器被附加到每个元素,但在大多数情况下您不希望这样做(节省内存)。将此“attrchange”侦听器附加到您要观察的元素。

于 2014-06-18T11:14:13.397 回答
53

我建议你重写 addClass 函数。你可以这样做:

// Create a closure
(function(){
    // Your base, I'm in it!
    var originalAddClassMethod = jQuery.fn.addClass;

    jQuery.fn.addClass = function(){
        // Execute the original method.
        var result = originalAddClassMethod.apply( this, arguments );

        // call your function
        // this gets called everytime you use the addClass method
        myfunction();

        // return the original result
        return result;
    }
})();

// document ready function
$(function(){
    // do stuff
});
于 2009-12-23T01:21:23.340 回答
22

只是一个概念证明:

查看要点以查看一些注释并保持最新:

https://gist.github.com/yckart/c893d7db0f49b1ea4dfb

(function ($) {
  var methods = ['addClass', 'toggleClass', 'removeClass'];

  $.each(methods, function (index, method) {
    var originalMethod = $.fn[method];

    $.fn[method] = function () {
      var oldClass = this[0].className;
      var result = originalMethod.apply(this, arguments);
      var newClass = this[0].className;

      this.trigger(method, [oldClass, newClass]);

      return result;
    };
  });
}(window.jQuery || window.Zepto));

用法很简单,只需在要观察和操作类的节点上添加一个新的侦听器即可:

var $node = $('div')

// listen to class-manipulation
.on('addClass toggleClass removeClass', function (e, oldClass, newClass) {
  console.log('Changed from %s to %s due %s', oldClass, newClass, e.type);
})

// make some changes
.addClass('foo')
.removeClass('foo')
.toggleClass('foo');
于 2013-03-22T13:52:32.220 回答
9

使用最新的 jquery 突变

var $target = jQuery(".required-entry");
            var observer = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    if (mutation.attributeName === "class") {
                        var attributeValue = jQuery(mutation.target).prop(mutation.attributeName);
                        if (attributeValue.indexOf("search-class") >= 0){
                            // do what you want
                        }
                    }
                });
            });
            observer.observe($target[0],  {
                attributes: true
            });

// 任何更新具有类required-entry 的div 的代码,该类位于 $target 中,例如 $target.addClass('search-class');

于 2016-08-22T20:26:26.690 回答
8

change()添加或删除 CSS 类或定义更改时不会触发。它在选择框值被选中或取消选中等情况下触发。

我不确定您的意思是是否更改了 CSS 类定义(可以通过编程方式完成,但很乏味且通常不推荐),或者是否向元素添加或删除了类。无论哪种情况,都无法可靠地捕捉到这种情况。

您当然可以为此创建自己的事件,但这只能被描述为建议性的。它不会捕获不属于您的代码。

或者,您可以覆盖/替换addClass()jQuery 中的(等)方法,但这不会在通过 vanilla Javascript 完成时捕获(尽管我猜您也可以替换这些方法)。

于 2009-12-23T00:23:02.747 回答
8

还有一种触发自定义事件的方法

用于监控 Html 元素 CSS 更改的 jQuery 插件 Rick Strahl

从上面引用

watch 插件通过连接到 FireFox 中的 DOMAttrModified、连接到 Internet Explorer 中的 onPropertyChanged 或使用带有 setInterval 的计时器来处理检测其他浏览器的更改来工作。不幸的是,WebKit 目前并不始终支持 DOMAttrModified,因此 Safari 和 Chrome 目前不得不使用较慢的 setInterval 机制。

于 2013-05-08T17:56:04.813 回答
6

好问题。我正在使用 Bootstrap 下拉菜单,并且需要在 Bootstrap 下拉菜单被隐藏时执行一个事件。当下拉菜单打开时,包含类名为“button-group”的div添加了一个类“open”;并且按钮本身的“aria-expanded”属性设置为true。当下拉菜单关闭时,“open”类将从包含的 div 中删除,并且 aria-expanded 从 true 切换为 false。

这让我想到了这个问题,即如何检测班级变化。

使用 Bootstrap,可以检测到“下拉事件”。在此链接中查找“下拉事件”。 http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp

这是在 Bootstrap Dropdown 上使用此事件的简单示例。

$(document).on('hidden.bs.dropdown', function(event) {
    console.log('closed');
});

现在我意识到这比被问到的一般问题更具体。但我想其他尝试使用 Bootstrap Dropdown 检测打开或关闭事件的开发人员会发现这很有帮助。像我一样,他们最初可能会走上简单地尝试检测元素类更改的道路(这显然不是那么简单)。谢谢。

于 2015-09-22T14:32:40.427 回答
5

如果您需要触发特定事件,您可以覆盖方法 addClass() 以触发名为“classadded”的自定义事件。

这里如何:

(function() {
    var ev = new $.Event('classadded'),
        orig = $.fn.addClass;
    $.fn.addClass = function() {
        $(this).trigger(ev, arguments);
        return orig.apply(this, arguments);
    }
})();

$('#myElement').on('classadded', function(ev, newClasses) {
    console.log(newClasses + ' added!');
    console.log(this);
    // Do stuff
    // ...
});
于 2013-02-08T13:58:17.877 回答
5

您可以绑定 DOMSubtreeModified 事件。我在这里添加一个示例:

HTML

<div id="mutable" style="width:50px;height:50px;">sjdfhksfh<div>
<div>
  <button id="changeClass">Change Class</button>
</div>

JavaScript

$(document).ready(function() {
  $('#changeClass').click(function() {
    $('#mutable').addClass("red");
  });

  $('#mutable').bind('DOMSubtreeModified', function(e) {
      alert('class changed');
  });
});

http://jsfiddle.net/hnCxK/13/

于 2016-08-15T19:34:12.383 回答
0

if you know a what event changed the class in the first place you may use a slight delay on the same event and the check the for the class. example

//this is not the code you control
$('input').on('blur', function(){
    $(this).addClass('error');
    $(this).before("<div class='someClass'>Warning Error</div>");
});

//this is your code
$('input').on('blur', function(){
    var el= $(this);
    setTimeout(function(){
        if ($(el).hasClass('error')){ 
            $(el).removeClass('error');
            $(el).prev('.someClass').hide();
        }
    },1000);
});

http://jsfiddle.net/GuDCp/3/

于 2014-05-14T16:24:13.210 回答
0
var timeout_check_change_class;

function check_change_class( selector )
{
    $(selector).each(function(index, el) {
        var data_old_class = $(el).attr('data-old-class');
        if (typeof data_old_class !== typeof undefined && data_old_class !== false) 
        {

            if( data_old_class != $(el).attr('class') )
            {
                $(el).trigger('change_class');
            }
        }

        $(el).attr('data-old-class', $(el).attr('class') );

    });

    clearTimeout( timeout_check_change_class );
    timeout_check_change_class = setTimeout(check_change_class, 10, selector);
}
check_change_class( '.breakpoint' );


$('.breakpoint').on('change_class', function(event) {
    console.log('haschange');
});
于 2017-02-05T18:42:42.430 回答