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

Posted

技术标签:

【中文标题】如何使用jQuery触发类更改事件?【英文标题】:How to fire an event on class change using jQuery? 【发布时间】:2013-10-24 11:05:36 【问题描述】:

我想要类似的东西:

$('#myDiv').bind('class "submission ok" added')
    alert('class "submission ok" has been added');
);

【问题讨论】:

【参考方案1】:

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

$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) 
    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/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。如果您需要支持旧版浏览器,则需要使用我在第一个示例中概述的方法。

【讨论】:

在完成这个答案后,我发现了这个:***.com/a/1950052/1579667 @Benj 这与我的原始答案相同(即使用trigger()),但请注意,由于使用bind(),它已经过时了。不过,我不确定它是如何“完成”任何事情的 在我的情况下,当 dom 节点具有特定类 MutationObserver 为我工作时,我需要触发一个事件 这是此解决方案的改进形式,带有过滤器***.com/a/42121795/12074818【参考方案2】:

你可以用你自己的替换原来的 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 Demo

这种方法确实假设类只能通过 jQuery addClass 和 removeClass 方法进行更改。如果以其他方式修改类(例如通过 DOM 元素直接操作类属性),则需要使用 MutationObservers 之类的东西,如此处接受的答案中所述。

还对这些方法进行了一些改进:

触发每个类的事件被添加(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 */ 
);

【讨论】:

这很好用,但在“代码的其余部分”中,事件处理程序应委托给目标选择器以允许绑定到新元素:$(parent_selector).on('classChanged', target_selector, function() /*...*/ );。我花了一段时间才明白为什么我的动态创建的元素没有触发处理程序。见learn.jquery.com/events/event-delegation【参考方案3】:

使用trigger 触发您自己的事件。每当您更改类时,添加带有名称的触发器

JS Fiddle DEMO

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

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

    alert("Red bg set ");
);

【讨论】:

【参考方案4】:

你可以使用这样的东西:

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

$(Selector).trigger('ClassChanged')

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

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

阅读更多关于触发器here

【讨论】:

事件的handler必须是触发事件的同一个item。 $(this).addClass('someClass'); $(Selector).trigger('ClassChanged') //必须是同一个Selector $(Selector).bind('ClassChanged', data, function()//stuff ); 看来你是从这里复制过来的,如果是的话,如果你也提供链接就好了***.com/questions/1950038/…

以上是关于如何使用jQuery触发类更改事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何触发jQuery asual的地址插件的更改事件?

jQuery 自动完成触发更改事件

如何在sqlalchemy中的值更改后触发事件

更改 <select> 的选项并使用 JavaScript 触发事件

如何将“更改”事件委托给正文的输入元素?

如何使用javascript触发jquery事件?