在 DOM 元素的样式对象更改后,您可以使用 javascript 钩子触发器吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10868104/
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-10-26 11:19:00  来源:igfitidea点击:

Can you have a javascript hook trigger after a DOM element's style object changes?

javascriptjquerycssjavascript-events

提问by user730569

An element has a javascript styleobject which contains the different names and values of css styles. I'd like to trigger a function every time this object changes without use of polling. Is there any way to do this in a way that is cross-browser compatible and would work reliably with third party code (because let's say you're providing a drop-in script)? Binding a javascript event like DOMAttrModifiedor DOMSubtreeModifiedwon't suffice because they don't work in Chrome.

一个元素有一个 javascriptstyle对象,其中包含 css 样式的不同名称和值。我想在每次这个对象改变而不使用 polling时触发一个函数。有什么方法可以跨浏览器兼容并且可以与第三方代码一起可靠地工作(因为假设您正在提供插入脚本)?绑定一个 javascript 事件,比如DOMAttrModifiedor 是DOMSubtreeModified不够的,因为它们在 Chrome 中不起作用。

回答by Selvakumar Arumugam

Edit 4:Live Demo

编辑 4:现场演示

$(function() {
  $('#toggleColor').on('click', function() {
    $(this).toggleClass('darkblue');
  }).attrchange({
    trackValues: true,
    callback: function(event) {
      $(this).html("<ul><li><span>Attribute Name: </span>" + event.attributeName + "</li><li><span>Old Value: </span>" + event.oldValue + "</li><li><span>New Value: </span>" + event.newValue + "</li></ul>");
    }
  });
});
body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 12px;
}
#toggleColor {
  height: 70px;
  width: 300px;
  padding: 5px;
  border: 1px solid #c2c2c2;
  background-color: #DBEAF9;
}
#toggleColor span {
  font-weight: bold;
}
#toggleColor.darkblue {
  background-color: #1A9ADA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://meetselva.github.io/attrchange/javascripts/attrchange.js"></script>
<p>Click below div to toggle class darkblue.</p>
<div id="toggleColor"></div>

Edit 3:I have put all this together as a plugin that can be downloaded from git attrchangeand here is the demo page.

编辑 3:我将所有这些放在一起作为一个插件,可以从 git attrchange下载,这里是演示页面

Edit 2:

编辑2:

  1. Fix for propertName in IE7 & IE8
  1. 修复 IE7 和 IE8 中的属性名称

Edit 1:

编辑1:

  1. Handle multiple elements
  2. Ordered the conditions as MutationObserver, DOMAttrModified and onpropertychange for better implementation.
  3. Added modified Attribute Name to the callback.
  1. 处理多个元素
  2. 将条件排序为 MutationObserver、DOMAttrModified 和 onpropertychange,以便更好地实现。
  3. 向回调添加了修改后的属性名称。

Thanks to @benvie for his feedback.

感谢@benvie 的反馈。

DEMO:http://jsfiddle.net/zFVyv/10/(Tested in FF 12, Chrome 19 and IE 7.)

演示:http : //jsfiddle.net/zFVyv/10/(在 FF 12、Chrome 19 和 IE 7 中测试。)

$(function() {
    (function($) {
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        function isDOMAttrModifiedSupported() {
            var p = document.createElement('p');
            var flag = false;

            if (p.addEventListener) p.addEventListener('DOMAttrModified', function() {
                flag = true
            }, false);
            else if (p.attachEvent) p.attachEvent('onDOMAttrModified', function() {
                flag = true
            });
            else return false;

            p.setAttribute('id', 'target');

            return flag;
        }

        $.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);
                });

            } else if (isDOMAttrModifiedSupported()) {
                return this.on('DOMAttrModified', function(e) {
                    callback.call(this, e.attrName);
                });
            } else if ('onpropertychange' in document.body) {
                return this.on('propertychange', function(e) {
                    callback.call(this, window.event.propertyName);
                });
            }
        }
    })(jQuery);

    $('.test').attrchange(function(attrName) {
        alert('Attribute: ' + attrName + ' modified ');
    }).css('height', 100);

});

Ref:

参考:

  1. Detect if DOMAttrModified supported
  2. DOMAttrModified for chrome
  3. Mutation Observer
  4. Why should we avoid using Mutation events?
  5. onPropertyChange IE
  1. 检测是否支持 DOMAttrModified
  2. DOMAttrModified for chrome
  3. 突变观察者
  4. 为什么我们应该避免使用 Mutation 事件?
  5. onPropertyChange IE

Mutation Observers is the proposed replacement for mutation events in DOM4. They are expected to be included in Firefox 14 and Chrome 18

Mutation Observers 是 DOM4 中突变事件的建议替代品。它们预计将包含在 Firefox 14 和 Chrome 18 中

Browser Support:

浏览器支持:

onpropertychange- is supported in IE (tested in IE 7)

onpropertychange- 支持 IE(在 IE 7 中测试)

DOMAttrModified- is supported in IE 9, FF and Opera

DOMAttrModified- 支持 IE 9、FF 和 Opera

MutationObservers- is very new and it worked fine in Chrome 18. Not sure how far it is supported and yet to be tested in Safari.

MutationObservers- 非常新,在Chrome 18 中运行良好。不确定它在多大程度上受支持并且尚未在 Safari 中进行测试。

Thanks @benvieon adding info about WebkitMutationObserver

感谢@benvie添加有关 WebkitMutationObserver 的信息

回答by Sepehr

EDIT2:

编辑2:

If you still want to use mutation observer, use this library: mutation-summary

如果你还想使用mutation observer,使用这个库:mutation-summary



EDIT:编辑:

As I said in my answer below and thanks to Vega for his comment, using things such as object.watchor mutation observersare not recommended for using in large apps. this is actual quote from MDN:

正如我在下面的回答中所说,并感谢 Vega 的评论,使用诸如object.watchmutation observers不推荐在大型应用程序中使用的东西。这是MDN 的实际报价:

Generally you should avoid using watch()and unwatch()when possible. These two methods are implemented only in Gecko, and they're intended primarily for debugging use. In addition, using watchpointshas a serious negative impact on performance, which is especially true when used on global objects, such as window. You can usually use settersand gettersor proxiesinstead. See Compatibility for details.

Warning

一般情况下,您应该避免使用watch()unwatch()在可能的情况下。这两种方法仅在 Gecko 中实现,它们主要用于调试用途。此外,使用观察点对性能有严重的负面影响,尤其是在全局对象上使用时尤其如此,例如窗口。您通常可以使用 settergetter代理代替。有关详细信息,请参阅兼容性。

警告

So if cross-browser compatibility is in your check list, Again, I highly suggest overriding setters and getters of styleobject.

因此,如果跨浏览器兼容性在您的检查列表中,我再次强烈建议覆盖对象的setters 和getters style



利用 object.watchobject.watch并在跨浏览器解决方案中牢记这些:

You may override getterand settermethods of element's styleobject too.

你可以覆盖gettersetter元素的方法style过于对象。

There is a jQuery plugin available for this, jQuery watch

有一个 jQuery 插件可用于此,jQuery watch

回答by Val

I have found this little plugin that does exactly that and it can be changed to add any mutation you wish... Even scrollHeight change listener.

我发现这个小插件可以做到这一点,并且可以对其进行更改以添加您希望的任何突变……甚至 scrollHeight 更改侦听器。

The plugin: http://www.jqui.net/jquery-projects/jquery-mutate-official/

插件:http: //www.jqui.net/jquery-projects/jquery-mutate-official/

here is the demo: http://www.jqui.net/demo/mutate/

这是演示:http: //www.jqui.net/demo/mutate/

回答by Muhammad Reda

You can use attrchange jQuery plugin. The main function of the plugin is to bind a listener function on attribute change of HTML elements.

您可以使用attrchange jQuery 插件。该插件的主要功能是绑定一个监听HTML元素属性变化的函数。

回答by o.v.

In an answer to a similar question, it was suggested that if you know that style-setting interactions would be performed via a standard interface (i.e. alwaysusing jQuery etc.) it was suggested that custom events be fired whenever the library method is called.

在对类似问题的回答中,有人建议如果您知道样式设置交互将通过标准接口执行(即始终使用 jQuery 等),则建议在调用库方法时触发自定义事件。

This would allow for a broader support matrix but would leave any property change ignored if performed without using the library method. It also appears that such an approach is not applicable to native settersas they cannot always be relied on.

这将允许更广泛的支持矩阵,但如果在不使用库方法的情况下执行,则会忽略任何属性更改。这种方法似乎也不适用于本地 setter,因为它们不能总是被依赖。

回答by Steve Binder

Even for all of the most modern browers there is no cross-browser way to achieve this. You would have to route all of your css style changes through a function which could trigger event listeners. This would be the cleanest method.

即使对于所有最现代的浏览器,也没有跨浏览器的方式来实现这一点。您必须通过一个可以触发事件侦听器的函数来路由所有 css 样式更改。这将是最干净的方法。