在jQuery中的CSS类更改上触发事件

我怎么能点燃一个事件,如果一个CSS类添加或使用jQuery改变? CSS类的改变是否会触发jQuery change()事件?< / p >

347206 次浏览

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

我不确定你的意思是如果CSS类定义被改变(这可以通过编程来完成,但很乏味,通常不推荐),或者如果一个类被添加或删除到一个元素。在这两种情况下,都没有办法可靠地捕捉到这种情况。

你当然可以为此创建你自己的事件,但这只能被描述为咨询。它不会捕获不是你的代码。

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

无论何时在脚本中更改类,都可以使用trigger来引发自己的事件。

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

但除此之外,没有固定的方法在类更改时触发事件。change()仅在focus离开输入已被更改的输入后触发。

$(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触发器的更多信息

我建议您重写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
});

依我看,更好的解决方案是结合@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
});
});

如果你需要触发一个特定的事件,你可以重写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
// ...
});

只是一个概念的证明:

查看要点,查看一些注释,并保持更新:

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');

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

一个jQuery插件来监视Html元素CSS的变化Rick Strahl

从上面引用

手表插件通过连接到FireFox中的DOMAttrModified来工作, 到onPropertyChanged在Internet Explorer,或通过使用计时器与 setInterval来处理对其他浏览器更改的检测。 不幸的是,WebKit不支持DOMAttrModified一致在 目前,Safari和Chrome不得不使用较慢的速度 setInterval机制。< / p >

如果你知道一个什么事件在第一个地方改变了类,你可以在相同的事件上使用轻微的延迟,并检查类。 示例< / p >

//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/

如果您想检测类更改,最好的方法是使用Mutation observer,它可以让您完全控制任何属性更改。但是,您需要自己定义监听器,并将其附加到您正在监听的元素。好消息是,一旦追加了listener,您就不需要手动触发任何事情。

$(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”监听器附加到你想观察的元素上。

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

这让我想到了一个问题,如何检测类的变化。

使用Bootstrap,可以检测到“下拉事件”。在这个链接中寻找“下拉事件”。 http://www.w3schools.com/bootstrap/bootstrap_ref_js_dropdown.asp < / p >

下面是在引导下拉列表中使用此事件的快速示例。

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

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

您可以绑定domsubtremodified事件。我在这里加一个例子:

超文本标记语言

<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/

使用最新的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
});

//在$target中更新div的所需入口类的任何代码 像target.addClass美元(“搜索类”);< / p >

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');
});