是否可以在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');
答案 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 );
答案 10 :(得分:-1)
我有同样的问题,所以我写了这个。它工作得很好。如果你将它与一些CSS过渡混合,看起来很棒。
function toggle_visibility(id) {
var e = document.getElementById("mjwelcome");
if(e.style.height == '')
e.style.height = '0px';
else
e.style.height = '';
}