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

问题描述 投票:0回答:4

我想要这样的东西:

$('#myDiv').bind('class "submission ok" added'){
    alert('class "submission ok" has been added');
});
javascript jquery jquery-events
4个回答
211
投票

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

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

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

更新 - 2015

这个问题似乎吸引了一些访问者,所以这里有一个更新的方法,无需使用新的

MutationObserver
修改现有代码即可使用:

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

observer.observe($div[0], {
  attributes: true,
  attributeFilter: ['class']
});

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

请注意,

MutationObserver
仅适用于较新的浏览器,特别是 Chrome 26、FF 14、IE 11、Opera 15 和 Safari 6。有关更多详细信息,请参阅 MDN。如果您需要支持旧版浏览器,那么您将需要使用我在第一个示例中概述的方法。


更新 - 2022 年

这是封装在 jQuery 扩展方法中的上述实现:

// extension method:
$.fn.onClassChange = function(cb) {
  return $(this).each((_, el) => {
    new MutationObserver(mutations => {
      mutations.forEach(mutation => cb && cb(mutation.target, mutation.target.className));
    }).observe(el, {
      attributes: true,
      attributeFilter: ['class'] // only listen for class attribute changes 
    });
  });
}

// usage:
const $foo = $("#foo").onClassChange((el, newClass) => console.log(`#${el.id} had its class updated to: ${newClass}`));
const $fizz = $("#fizz").onClassChange((el, newClass) => console.log(`#${el.id} had its class updated to: ${newClass}`));

// trigger
$('#trigger').on('click', () => {
  $foo.removeClass('red');
  $fizz.addClass('green dark-bg');
});
.red {
  color: #C00;
}

.green {
  color: #0C0;
}

.dark-bg {
  background-color: #666;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button id="trigger">Change classes</button>
<div id="foo" class="bar red">#foo.bar</div>
<div id="fizz" class="buzz">#fizz.buzz</div>


24
投票

您可以用自己的函数替换原始的 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(){ /*...*/ });

更新:

JS Fiddle 演示

这种方法确实假设类只能通过 jQuery addClass 和 removeClass 方法更改。如果以其他方式修改类(例如通过 DOM 元素直接操作类属性),则需要使用类似

MutationObserver
的内容,如此处接受的答案中所述。

还有对这些方法的一些改进:

  • 触发添加 (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
                      }
                  });
                  if( 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);
                      }
                  });
                  if( prevClasses != this.getAttribute('class') ) $this.trigger('classChanged');
              });
              return this;
          }
      })($.fn.removeClass);
    

    
    
  • 使用这些替换函数,您可以通过检查回调函数的参数来处理通过 classChanged 更改的任何类或添加或删除的特定类:

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



10
投票
trigger

触发您自己的事件。当您更改班级时,请添加带有名称的触发器

JS 小提琴演示 $("#main").on('click', function () { $("#chld").addClass("bgcolorRed").trigger("cssFontSet"); }); $('#chld').on('cssFontSet', function () { alert("Red bg set "); });



2
投票

$(this).addClass('someClass'); $(Selector).trigger('ClassChanged') $(otherSelector).bind('ClassChanged', data, function(){//stuff });

但除此之外,不,没有预定义的函数可以在类更改时触发事件。 

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

此处

© www.soinside.com 2019 - 2024. All rights reserved.