Javascript 是否可以收听“风格改变”事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2157963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:00:21  来源:igfitidea点击:

Is it possible to listen to a "style change" event?

javascriptjquery

提问by David Hellsing

Is it possible to create an event listener in jQuery that can be bound to any style changes? For example, if I want to "do" something when an element changes dimensions, or any other changes in the style attribute I could do:

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

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

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

It would be really useful.

这将非常有用。

Any ideas?

有任何想法吗?

UPDATE

更新

Sorry for answering this myself, but I wrote a neat solution that might fit someone else:

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

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

This will temporary override the internal prototype.css method and the redefine it with a trigger at the end. So it works like this:

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

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

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

采纳答案by Josh Stodola

Since jQuery is open-source, I would guess that you could tweak the cssfunction to call a function of your choice every time it is invoked (passing the jQuery object). Of course, you'll want to scour the jQuery code to make sure there is nothing else it uses internally to set CSS properties. Ideally, you'd want to write a separate plugin for jQuery so that it does not interfere with the jQuery library itself, but you'll have to decide whether or not that is feasible for your project.

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

回答by codebox

Things have moved on a bit since the question was asked - it is now possible to use a MutationObserverto detect changes in the 'style' attribute of an element, no jQuery required:

自从提出这个问题以来,事情已经发生了一些变化 - 现在可以使用MutationObserver来检测元素的“样式”属性的变化,不需要 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'] });

The argument that gets passed to the callback function is a MutationRecordobject that lets you get hold of the old and new style values.

传递给回调函数的参数是一个MutationRecord对象,可让您获取旧样式值和新样式值。

Support is good in modern browsersincluding IE 11+.

包括 IE 11+ 在内的现代浏览器中支持良好

回答by Mike Allen

The declaration of your event object has to be inside your new css function. Otherwise the event can only be fired once.

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

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

回答by ccsakuweb

I think the best answer if from Mike in the case you can't launch your event because is not from your code. But I get some errors when I used it. So I write a new answer for show you the code that I use.

我认为最好的答案是来自 Mike,以防您无法启动您的活动,因为它不是来自您的代码。但是我在使用时遇到了一些错误。所以我写了一个新的答案来向你展示我使用的代码。

Extension

延期

// 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;
    }
})();

Usage

用法

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

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

I got error because var ev = new $.Event('style'); Something like style was not defined in HtmlDiv.. I removed it, and I launch now $(this).trigger("stylechanged"). Another problem was that Mike didn't return the resulto of $(css, ..) then It can make problems in some cases. So I get the result and return it. Now works ^^ In every css change include from some libs that I can't modify and trigger an event.

我得到错误,因为 var ev = new $.Event('style'); HtmlDiv 中没有定义样式之类的东西。我删除了它,现在启动 $(this).trigger("stylechanged")。另一个问题是 Mike 没有返回 $(css, ..) 的结果,那么在某些情况下它可能会出现问题。所以我得到结果并返回它。现在可以使用 ^^ 在每个 css 更改中都包含一些我无法修改和触发事件的库。

回答by droo

As others have suggested, if you have control over whatever code is changing the style of the element you could fire a custom event when you change the element's height:

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

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

Otherwise, although pretty resource-intensive, you could set a timer to periodically check for changes to the element's height...

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

回答by Teja Kantamneni

There is no inbuilt support for the style change event in jQuery or in java script. But jQuery supports to create custom event and listen to it but every time there is a change, you should have a way to trigger it on yourself. So it will not be a complete solution.

jQuery 或 Java 脚本中没有对样式更改事件的内置支持。但是 jQuery 支持创建自定义事件并侦听它,但是每次发生更改时,您都应该有一种方法可以自己触发它。所以它不会是一个完整的解决方案。

回答by user889030

you can try Jquery plugin , it trigger events when css is change and its easy to use

你可以试试Jquery插件,它在css改变时触发事件并且它易于使用

http://meetselva.github.io/#gist-section-attrchangeExtension
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
  }
});

回答by pixeline

Interesting question. The problem is that height() does not accept a callback, so you wouldn't be able to fire up a callback. Use either animate() or css() to set the height and then trigger the custom event in the callback. Here is an example using animate() , tested and works (demo), as a proof of concept :

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

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

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

回答by Nir Hemed

Just adding and formalizing @David 's solution from above:

只需从上面添加和形式化@David 的解决方案:

Note that jQuery functions are chainable and return 'this' so that multiple invocations can be called one after the other (e.g $container.css("overflow", "hidden").css("outline", 0);).

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

So the improved code should be:

所以改进后的代码应该是:

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

回答by halfbit

How about jQuery cssHooks?

jQuery cssHooks 怎么样?

Maybe I do not understand the question, but what you are searching for is easily done with cssHooks, without changing css()function.

也许我不明白这个问题,但是你正在寻找的东西很容易用 完成cssHooks,而无需改变css()功能。

copy from documentation:

从文档中复制:

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

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