是否可以倾听“风格变化”事件?

时间:2010-01-28 21:09:10

标签: javascript jquery

是否可以在jQuery中创建一个可以绑定到任何样式更改的事件侦听器?例如,如果我想在元素更改维度时“执行”某些操作,或者我可以执行样式属性中的任何其他更改:

$('div').bind('style', function() {
    console.log($(this).css('height'));
});

$('div').height(100); // yields '100'

这将非常有用。

有什么想法吗?

更新

很抱歉自己回答这个问题,但我写了一个可能适合其他人的简洁解决方案:

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

这将临时覆盖内部prototype.css方法,并在最后用触发器重新定义它。所以它的工作原理如下:

$('p').bind('style', function(e) {
    console.log( $(this).attr('style') );
});

$('p').width(100);
$('p').css('color','red');

11 个答案:

答案 0 :(得分:221)

自提出问题以来,情况有所改变 - 现在可以使用MutationObserver来检测元素'style'属性的变化,不需要jQuery:

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        console.log('style changed!');
    });    
});

var target = document.getElementById('myId');
observer.observe(target, { attributes : true, attributeFilter : ['style'] });

传递给回调函数的参数是一个MutationRecord对象,可以让你掌握旧的和新的样式值。

支持是good in modern browsers,包括IE 11 +。

答案 1 :(得分:18)

由于jQuery是开源的,我猜你可以调整css函数来在每次调用时调用你选择的函数(传递jQuery对象)。当然,您需要搜索jQuery代码以确保其内部没有任何其他内容用于设置CSS属性。理想情况下,你想为jQuery编写一个单独的插件,这样它就不会干扰jQuery库本身,但是你必须决定它对你的项目是否可行。

答案 2 :(得分:18)

您的事件对象的声明必须在您的新css函数中。否则,事件只能被触发一次。

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

答案 3 :(得分:13)

如果您无法启动活动,我认为最好的答案来自Mike,因为这不是来自您的代码。但是当我使用它时,我遇到了一些错误。所以我写了一个新的答案,告诉你我使用的代码。

扩展

// Extends functionality of ".css()"
// This could be renamed if you'd like (i.e. "$.fn.cssWithListener = func ...")
(function() {
    orig = $.fn.css;
    $.fn.css = function() {
        var result = orig.apply(this, arguments);
        $(this).trigger('stylechanged');
        return result;
    }
})();

用法

// Add listener
$('element').on('stylechanged', function () {
    console.log('css changed');
});

// Perform change
$('element').css('background', 'red');

我收到错误因为var ev = new $ .Event('style');在HtmlDiv中没有​​定义类似样式的东西..我删除它,然后我现在启动$(this).trigger(“stylechanged”)。另一个问题是迈克没有返回$(css,..)的结果然后它在某些情况下会出现问题。所以我得到了结果并将其返回。现在工作^^在每个css中,包含一些我无法修改并触发事件的库。

答案 4 :(得分:4)

正如其他人所建议的那样,如果您可以控制更改元素样式的任何代码,则可以在更改元素高度时触发自定义事件:

$('#blah').bind('height-changed',function(){...});
...
$('#blah').css({height:'100px'});
$('#blah').trigger('height-changed');

否则,虽然资源非常密集,但您可以设置一个计时器来定期检查元素高度的变化......

答案 5 :(得分:2)

jQuery或java脚本中没有内置的样式更改事件支持。但是jQuery支持创建自定义事件并监听它,但每次有变化时,你应该有办法自己触发它。所以它不是一个完整的解决方案。

答案 6 :(得分:2)

您可以尝试使用Jquery插件,它会在css发生变化时触发事件并且易于使用

http://meetselva.github.io/#gist-section-attrchangeExtension
 $([selector]).attrchange({
  trackValues: true, 
  callback: function (e) {
    //console.log( '<p>Attribute <b>' + e.attributeName +'</b> changed from <b>' + e.oldValue +'</b> to <b>' + e.newValue +'</b></p>');
    //event.attributeName - Attribute Name
    //event.oldValue - Prev Value
    //event.newValue - New Value
  }
});

答案 7 :(得分:1)

有趣的问题。问题是height()不接受回调,因此您将无法启动回调。使用animate()或css()设置高度,然后在回调中触发自定义事件。以下是使用animate(),测试和工作(demo)作为概念证明的示例:

$('#test').bind('style', function() {
    alert($(this).css('height'));
});

$('#test').animate({height: 100},function(){
$(this).trigger('style');
}); 

答案 8 :(得分:1)

从上面添加并正式化@David的解决方案:

请注意,jQuery函数是可链接的并返回'this',以便可以一个接一个地调用多个调用(例如$container.css("overflow", "hidden").css("outline", 0);)。

所以改进的代码应该是:

(function() {
    var ev = new $.Event('style'),
        orig = $.fn.css;
    $.fn.css = function() {
        var ret = orig.apply(this, arguments);
        $(this).trigger(ev);
        return ret; // must include this
    }
})();

答案 9 :(得分:0)

jQuery cssHooks怎么样?

也许我不明白这个问题,但是使用cssHooks可以轻松完成您要搜索的内容,而无需更改css()函数。

从文档中复制:

(function( $ ) {

// First, check to see if cssHooks are supported
if ( !$.cssHooks ) {
  // If not, output an error message
  throw( new Error( "jQuery 1.4.3 or above is required for this plugin to work" ) );
}

// Wrap in a document ready call, because jQuery writes
// cssHooks at this time and will blow away your functions
// if they exist.
$(function () {
  $.cssHooks[ "someCSSProp" ] = {
    get: function( elem, computed, extra ) {
      // Handle getting the CSS property
    },
    set: function( elem, value ) {
      // Handle setting the CSS value
    }
  };
});

})( jQuery ); 

https://api.jquery.com/jQuery.cssHooks/

答案 10 :(得分:-1)

我有同样的问题,所以我写了这个。它工作得很好。如果你将它与一些CSS过渡混合,看起来很棒。

function toggle_visibility(id) {
   var e = document.getElementById("mjwelcome");
   if(e.style.height == '')
      e.style.height = '0px';
   else
      e.style.height = '';
}